Skip to content

Mental model

Three nouns cover almost everything in pkg/bb.

  • A Flow runs one or more agents over an incoming chat, collects their replies, and hands the result to the next flow.
  • Flows compose: a group of flows is itself a flow (Select, All, One, Group), and Next chains them into a longer flow.
  • An Agent is build-time configuration (model, role, schema, handler). It cannot act on its own.
  • A Turn and a ModelChat are the agent live on one message — the two handles an OnMessage handler receives. turn faces the client (Reply/Stream/Call/Select); chat faces the model (Add/Ask/Resolve). Neither can reconfigure the agent — the compiler enforces both splits, so an invalid state (a builder that asks, a running turn that changes its model) is unrepresentable.

The smallest brain

go
func main() {
    ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
    defer stop()

    bb.WithModel(bb.NewModel().WithName("gpt-4o-mini")).WithTag("chat")

    agent := bb.NewAgent(). // no model: inherits the flow's / the default
        WithRole(bb.Role("You are a terse assistant."))
    flow := bb.NewFlow().WithModel(bb.NewModel("chat")).WithAgent(agent)

    bb.Serve(ctx, flow) // OpenAI + Anthropic at :8080
}

A default (no-OnMessage) agent just asks the model with the incoming chat and replies — forwarding the caller's tools and relaying the model's tool calls untouched, so it behaves exactly like the model behind it. That is the whole walking skeleton; everything else in these docs is what you add to it.

Two handles, two directions

An agent mediates two opposite conversations — the client that called your brain, and the model your brain calls — and the same nouns (a message, a tool call, a tool result) flow both ways. So they are kept as separate objects, and which one you touch says which direction you mean:

turn bb.Turn — the client sidechat bb.ModelChat — the model side
readMessages, Last(), Request(), ToolResults()Messages()
writeReply, Stream, CallAdd, WithTools, ForwardTools, WithToolChoice
actSelectAsk, AskWith, Resolve

chat.Ask asks the model; turn.Reply answers the client. chat.Add builds the prompt; turn.Call asks the client to run something. Neither can reconfigure the agent — there are no With… methods for that on either handle, so runtime self-modification stays impossible by construction.

This split is the single idea to hold onto before reading the rest of the concept pages — every API in pkg/bb is an instance of "which side of the conversation is this for."

Continue to Flows, agents & turns for the full API surface built on top of this model.

A tree of flows and agents, disguised as a model.