Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use flake
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ go.work.sum
.env

/tmp
/bin
/bin

# nix
.direnv/
71 changes: 59 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,79 @@

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![Test](https://github.com/bit8bytes/beago/actions/workflows/tests.yml/badge.svg) ![Sec Scan](https://github.com/bit8bytes/beago/actions/workflows/sec_scan.yml/badge.svg)

beago provides composable building blocks for LLM-powered Go applications — pipes for structured output, agents for tool-using reasoning loops, and stores for conversation history. The core library has no external dependencies.
beago brings the Unix philosophy to LLM applications: small, focused handlers connected by pipes. Each handler reads from an `io.Reader`, transforms the stream, and writes to an `io.Writer` — exactly like Unix programs connected with `|`. The core library has no external dependencies.

## The Unix Pipe Model

Unix pipes let you compose small programs into powerful workflows:

```
echo "text" | translate | summarise | fmt
```

beago works the same way, but for LLM pipelines:

```go
pipe.Execute(ctx, os.Stdin, os.Stdout,
llm.Prompt("Translate to French."),
llm.Generate(model), // stdin | translate
llm.Prompt("Summarise in one sentence."),
llm.Generate(model), // | summarise
)
```

Each `pipe.Handler` is a composable unit. Handlers are chained with `pipe.Execute`, looped with `pipe.Loop`, and debugged with `pipe.Tee` — mirroring Unix's `tee(1)`.

## Core Concepts

- **Pipes** — simple `Input → LLM → Output` pipelines with typed, structured responses
- **Pipe** — the core primitive: a `Handler` that reads `io.Reader` → transforms → writes `io.Writer`
- **Execute** — chains handlers sequentially, connecting each output to the next input via `io.Pipe`
- **Loop** — runs a handler chain repeatedly, feeding each iteration's output as the next input; stops on `ErrDone` or a max iteration count
- **Tee** — splits the stream like Unix `tee(1)`: passes data through while copying to a second writer for debugging
- **Agents** — ReAct (Reasoning + Acting) loops that interleave LLM reasoning with tool execution
- **Stores** — tamper-evident message history with a SHA-256 hash chain, keeping LLMs stateful across turns
- **Tools** — implement the `Tool` interface to give agents new capabilities

## Quick Start

```go
// Pipe: send messages and get structured output
pipe := pipes.New(messages, model, parser)
result, _ := pipe.Invoke(ctx)
// Single handler: pipe stdin through an LLM to stdout
// echo "What is 2+2?" | go run .
pipe.Execute(ctx, os.Stdin, os.Stdout,
llm.Generate(model),
)
```
See [Pipe](/examples/pipes/json/main.go) for full working `pipe` example.

```go
// Agent: reason and act with tools
agent, _ := agents.NewReAct(ctx, model, tools, storage)
agent.Task(ctx, "Use the helloWorld tool with name Beago")
res, _ := runner.New(agent).Run(ctx)
// Chain handlers: translate then summarise
pipe.Execute(ctx, os.Stdin, os.Stdout,
llm.Prompt("Translate to French."),
llm.Generate(model),
llm.Prompt("Summarise in one sentence."),
llm.Generate(model),
)
```

See [Agent](/examples/agents/hello/main.go) for full working `agent` example.
```go
// Loop until the LLM outputs "DONE"
pipe.Execute(ctx, os.Stdin, os.Stdout,
pipe.Loop(10,
llm.Generate(model),
pipe.Exit(func(b []byte) bool {
return bytes.Contains(b, []byte("DONE"))
}),
),
)
```

## Examples

| Example | Description |
|---|---|
| [pipe](/examples/pipe/main.go) | Single LLM call — the simplest pipe |
| [pipe/tee](/examples/pipe/tee/main.go) | Split the stream with `Tee` to inspect output |
| [pipe/chain](/examples/pipe/chain/main.go) | Chain two LLM calls: translate → summarise |
| [pipe/loop](/examples/pipe/loop/main.go) | Loop until a stop condition is met |
| [agents](/examples/agents/main.go) | ReAct agent with tools |

## Contributions

Expand Down
160 changes: 0 additions & 160 deletions agents/agents.go

This file was deleted.

22 changes: 0 additions & 22 deletions agents/messages.go

This file was deleted.

Loading
Loading