|
2 | 2 |
|
3 | 3 | [](https://opensource.org/licenses/MIT)   |
4 | 4 |
|
5 | | -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. |
| 5 | +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. |
| 6 | + |
| 7 | +## The Unix Pipe Model |
| 8 | + |
| 9 | +Unix pipes let you compose small programs into powerful workflows: |
| 10 | + |
| 11 | +``` |
| 12 | +echo "text" | translate | summarise | fmt |
| 13 | +``` |
| 14 | + |
| 15 | +beago works the same way, but for LLM pipelines: |
| 16 | + |
| 17 | +```go |
| 18 | +pipe.Execute(ctx, os.Stdin, os.Stdout, |
| 19 | + llm.Prompt("Translate to French."), |
| 20 | + llm.Generate(model), // stdin | translate |
| 21 | + llm.Prompt("Summarise in one sentence."), |
| 22 | + llm.Generate(model), // | summarise |
| 23 | +) |
| 24 | +``` |
| 25 | + |
| 26 | +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)`. |
6 | 27 |
|
7 | 28 | ## Core Concepts |
8 | 29 |
|
9 | | -- **Pipes** — simple `Input → LLM → Output` pipelines with typed, structured responses |
| 30 | +- **Pipe** — the core primitive: a `Handler` that reads `io.Reader` → transforms → writes `io.Writer` |
| 31 | +- **Execute** — chains handlers sequentially, connecting each output to the next input via `io.Pipe` |
| 32 | +- **Loop** — runs a handler chain repeatedly, feeding each iteration's output as the next input; stops on `ErrDone` or a max iteration count |
| 33 | +- **Tee** — splits the stream like Unix `tee(1)`: passes data through while copying to a second writer for debugging |
10 | 34 | - **Agents** — ReAct (Reasoning + Acting) loops that interleave LLM reasoning with tool execution |
11 | | -- **Stores** — tamper-evident message history with a SHA-256 hash chain, keeping LLMs stateful across turns |
12 | 35 | - **Tools** — implement the `Tool` interface to give agents new capabilities |
13 | 36 |
|
14 | 37 | ## Quick Start |
15 | 38 |
|
16 | 39 | ```go |
17 | | -// Pipe: send messages and get structured output |
18 | | -pipe := pipes.New(messages, model, parser) |
19 | | -result, _ := pipe.Invoke(ctx) |
| 40 | +// Single handler: pipe stdin through an LLM to stdout |
| 41 | +// echo "What is 2+2?" | go run . |
| 42 | +pipe.Execute(ctx, os.Stdin, os.Stdout, |
| 43 | + llm.Generate(model), |
| 44 | +) |
20 | 45 | ``` |
21 | | -See [Pipe](/examples/pipes/json/main.go) for full working `pipe` example. |
22 | 46 |
|
23 | 47 | ```go |
24 | | -// Agent: reason and act with tools |
25 | | -agent, _ := agents.NewReAct(ctx, model, tools, storage) |
26 | | -agent.Task(ctx, "Use the helloWorld tool with name Beago") |
27 | | -res, _ := runner.New(agent).Run(ctx) |
| 48 | +// Chain handlers: translate then summarise |
| 49 | +pipe.Execute(ctx, os.Stdin, os.Stdout, |
| 50 | + llm.Prompt("Translate to French."), |
| 51 | + llm.Generate(model), |
| 52 | + llm.Prompt("Summarise in one sentence."), |
| 53 | + llm.Generate(model), |
| 54 | +) |
28 | 55 | ``` |
29 | 56 |
|
30 | | -See [Agent](/examples/agents/hello/main.go) for full working `agent` example. |
| 57 | +```go |
| 58 | +// Loop until the LLM outputs "DONE" |
| 59 | +pipe.Execute(ctx, os.Stdin, os.Stdout, |
| 60 | + pipe.Loop(10, |
| 61 | + llm.Generate(model), |
| 62 | + pipe.Exit(func(b []byte) bool { |
| 63 | + return bytes.Contains(b, []byte("DONE")) |
| 64 | + }), |
| 65 | + ), |
| 66 | +) |
| 67 | +``` |
| 68 | + |
| 69 | +## Examples |
| 70 | + |
| 71 | +| Example | Description | |
| 72 | +|---|---| |
| 73 | +| [pipe](/examples/pipe/main.go) | Single LLM call — the simplest pipe | |
| 74 | +| [pipe/tee](/examples/pipe/tee/main.go) | Split the stream with `Tee` to inspect output | |
| 75 | +| [pipe/chain](/examples/pipe/chain/main.go) | Chain two LLM calls: translate → summarise | |
| 76 | +| [pipe/loop](/examples/pipe/loop/main.go) | Loop until a stop condition is met | |
| 77 | +| [agents](/examples/agents/main.go) | ReAct agent with tools | |
31 | 78 |
|
32 | 79 | ## Contributions |
33 | 80 |
|
|
0 commit comments