Routing with Select
Select groups flows so an upstream agent picks one by id:
go
brain := router.Next(bb.Select(talk, remember, house)).Next(bb.Respond)- Each
Selectmember must set an id withWithId; a member without one is ignored (with a warning). - An agent picks a member with
turn.Select(id). An unknown id is a loud error at request time, never a silent misroute. - Declaring an agent's exits with
Selects(id…)adds a startup check (bb.Serve/bb.Handlerverifies every declared exit is a group member) before any request runs. It is optional — declare it when you want the boot-time guarantee. - Within one agent, the last
Selectwins (program order). Across concurrent agents, two different selects is a louderror, not a race; the same id is fine.
A typical intent router
The pattern behind both reference brains: classify with a model + typed schema, then dispatch.
go
type intent struct {
Intent string `json:"intent" enum:"talk,house,remember" doc:"the chosen capability"`
Reason string `json:"reason"`
}
router := bb.NewAgent().
WithModel(bb.NewModel("cheap")).
WithSchema(bb.Schema[intent]()).
Selects("talk", "house", "remember").
OnMessage(func(ctx context.Context, turn bb.Turn, chat bb.ModelChat) error {
chat.Add(turn.Last())
reply, err := chat.Ask()
if err != nil {
return err
}
it := bb.Extract[intent](reply)
turn.Select(it.Intent)
return nil
})
brain := bb.NewFlow().WithAgent(router).
Next(bb.Select(talkFlow, houseFlow, rememberFlow)).
Next(bb.Respond)Selects(...) is worth adding here: a typo in it.Intent, or a capability you forgot to add to the Select group, fails at bb.Serve startup instead of the first time a live classification happens to pick it.
See Concurrency for what happens when multiple flows in a Select group's siblings (All/One/Group) run at once.