secai is a Golang framework for Reasoning AI Workflows, implemented using a unique state machine which thrives in complexity. It's a solid foundation for complex, proactive, and long-lived AI Agents with deep and structured memory. Each bot ships with embedded devtools and several UIs. The execution flow is graph-based, which allows for precise behavior modeling of agents, including interruptions, concurrency, and fault tolerance.
It's a sophisticated replacement for frameworks like LangGraph and offers deeply relational consensus of state.
Live debugger | Live SQL | Read logs | Browse files
| Debugger | REPL | DB | DB | Log |
|
|
|
|
|
| Dashboard | ||||
|
AI-gent Cook on qwen3-vl-30b
Screenshots and YouTube are also available.
Note
User demo (7m captions-only) showcasing a cooking assistant which helps to pick a recipe from ingredients AND cook it.
Click to see screenshots
| Intro | AI-gent Cook | Debugger 1 | Debugger 2 | Memory & Stories |
|
|
|
|
|
| User Interfaces | Outro | |||
|
|
|||
| Diagram | ||||
|
|
||||
Screenshots and YouTube are also available.
Note
Platform demo (5m captions-only), showcasing all nine ways an agent can be seen, in addition to the classic chat view.
- multi-prompt agency
- a single agent/bot is built of several AI prompts
- each state can have a prompt bound to it, with dedicated history and documents
- atomic consensus with relations and negotiation
- eg states excluding each other can't be active simultaneously
- dedicated DSL layer for bot schema
- suitable for non-coding authors
- structured prompt input/output via JSON schemas
- declarative flow definitions for non-linear flows
- cancellation support (interrupts)
- choice menu (list of offers)
- prompt history
- embedded SQLite
- JSONL log
- "latest prompt" files
- proactive stories with actors
- stories have actions and progress
- LLM-sourced story switching (orienting)
- on prompts and timeouts
- dynamic flow graph for the memory
- LLM creates an actionable state-machine
- TUIs and WebAssembly PWAs for user interfaces
- precision
- correctness
- granular debugging
All devtools are available on the web, some also as TUIs, and some as regular files. Everything is shipped as a single file.
- debugger
- REPL
- diagrams (D2 SVGs)
- DB browser
- log viewer
- observability (OpenTelemetry, Prometheus, Loki)
- Golang & WASM
- asyncmachine-go for graph control flow
- instructor-go for AI APIs
- invopop/jsonschema for prompt schemas
- aRPC for network transparency
- a single agent can span across multiple servers and browsers
- cview for TUIs
- go-app for web UIs
- ncruces for SQLite
- Agent (actor)
- state-machine schema
- prompts
- tools
- Tool (actor)
- state-machine schema
- Memory
- state-machine schema
- Prompt (state)
- params schema
- result schema
- history log
- documents
- Stories (state)
- actors (state machines)
- actions
- progress
- Document
- title
- content
- Download a binary release of AI-gent Cook (Linux, macOS, Windows)
$ ./ai-gent-cook
AI-gent Cook v0.5.0
Web:
- http://localhost:12854
- http://localhost:12854/agent
Files:
- config: config.kdl
- log: tmp-cook/cook.jsonl
TUI:
- http://localhost:7856
- ssh localhost -p 7955 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no
REPL:
- http://localhost:13179
- ./cook repl
Log:
- http://localhost:12858
- ./cook log --tail
- tail -f tmp-cook/cook.jsonl -n 100 | fblog -d -x msg -x time -x level
Debugger:
- http://localhost:13178
- files: http://localhost:13171
- ssh localhost -p 13172 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no
DB:
- Base: http://localhost:13180
- Agent: http://localhost:13181
- History: http://localhost:13182
https://AI-gents.workCode snippets from state and prompt schemas of examples/cook. Both schemas are pure and debuggable Golang code.
// CookStatesDef contains all the states of the Cook state machine.
type CookStatesDef struct {
*am.StatesBase
// ...
// prompts
RestoreJokes string
GenJokes string
JokesReady string
GenSteps string
// StepsReady implies the steps have been translated into actionable memory.
StepsReady string
GenStepComments string
StepCommentsReady string
// inherit from AgentLLM
*ssllm.AgentLLMStatesDef
}
// ...
// CookSchema represents all relations and properties of CookStates.
var CookSchema = SchemaMerge(
// inherit from AgentLLM
ssllm.LLMAgentSchema,
am.Schema{
// gen AI
ssC.RestoreJokes: {
Auto: true,
Require: S{ssC.DBReady, ssC.CharacterReady},
Remove: sgC.Jokes,
},
ssC.GenJokes: {
Require: S{ssC.CharacterReady, ssC.DBReady},
Remove: sgC.Jokes,
Tags: S{ssbase.TagPrompt},
},
ssC.JokesReady: {Remove: sgC.Jokes},
ssC.GenSteps: {
Auto: true,
Require: S{ssC.StoryCookingStarted},
Remove: S{ssC.StepsReady},
Tags: S{ssbase.TagPrompt},
},
ssC.StepsReady: {
Require: S{ssC.RecipeReady},
Remove: S{ssC.GenSteps},
},
ssC.GenStepComments: {
Auto: true,
Require: S{ssC.StoryCookingStarted, ssC.StepsReady},
Remove: S{ssC.StepCommentsReady},
Tags: S{ssbase.TagPrompt},
},
ssC.StepCommentsReady: {Remove: S{ssC.GenStepComments}},
ssC.Orienting: {
Multi: true,
Tags: S{ssbase.TagPrompt},
},
ssC.OrientingMove: {},
})The comments attached to Params* and Result* are sent over to AI models.
// RECIPE
type PromptRecipePicking = secai.Prompt[ParamsRecipePicking, ResultRecipePicking]
func NewPromptRecipePicking(agent shared.AgentBaseAPI) *PromptRecipePicking {
return secai.NewPrompt[ParamsRecipePicking, ResultRecipePicking](
agent, ss.StoryRecipePicking, `
- You're a database of cooking recipes.
`, `
1. Suggest recipes based on user's ingredients.
2. If possible, find 1 extra recipe, which is well known, but 1-3 ingredients are missing.
3. Summarize the propositions using the character's personality.
`, `
- Limit the amount of recipes to the requested number (excluding the extra recipe).
- Include an image URL per each recipe
`)
}
type Recipe struct {
Name string
Desc string
Steps string
}
type ParamsRecipePicking struct {
// List of available ingredients.
Ingredients []Ingredient
// The number of recipes needed.
Amount int
}
type ResultRecipePicking struct {
// List of proposed recipes
Recipes []Recipe
// Extra recipe with unavailable ingredients.
ExtraRecipe Recipe
// Message to the user, summarizing the recipes. Max 3 sentences.
Summary string
}
// ...
var StoryRecipePicking = &shared.Story{
StoryInfo: shared.StoryInfo{
State: ss.StoryRecipePicking,
Title: "Recipe Picking",
Desc: "The bot offers some recipes, based on the ingredients.",
},
Agent: shared.StoryActor{
Trigger: amhelp.Cond{
Is: am.S{ss.Ready, ss.IngredientsReady},
Not: am.S{ss.RecipeReady},
},
},
}Read the full state schema and prompt schema.
- secai: API / Docs
- asyncmachine-go: API / Docs
- instructor-go: API / Docs
- cview: API
We can use one of the examples as a starting template. It allows for further semver updates of the base framework.
- Choose the source example
export SECAI_EXAMPLE=cookexport SECAI_EXAMPLE=research(broken sincev0.4.0)
git clone https://github.com/pancsta/secai.git- install task
./secai/scripts/deps.sh - copy the agent
cp -R secai/examples/$SECAI_EXAMPLE MYAGENT cd MYAGENT && go mod init github.com/USER/MYAGENT- get fresh configs
task sync-taskfiletask sync-configs
- start it
task start - look around
task --list-all - configure the bot
$EDITOR config.kdl
secai differs from other AI agents / workflows frameworks in the way it treats AI prompts. Most frameworks call each prompt an "agent", while secai treats prompts as simple DB queries with IoC (Inversion of Control). Tool usage happens manually through typesafe params / results. This approach increases determinism, safety, and overfall control. This multi-prompt workflow forms an actual bot / agent. This does not mean agents can't be composed into larger groups, which happens simply on the state level (via piping / aRPC), as the underlying workflow engine (asyncmachine) doesn't depend on AI at all.
The flow graph, unlike in regular workflows, is not path-based - each node (state) can be activated anytime (same as calling a function), and the edges between nodes are meant to resolve the state consensus. It's a directed multi-graph of states with a negotiation phase.
arpc offers CLI access to remote agents, including subscription. It's perfect for quick and simple integrations, scripts, or experiments.
Example: $ arpc -f tmp/research.addr -- when . Requesting && echo "REQUESTING"
- Connect to the address from
tmp/research.addr - When the last connected agent (
.) goes into stateRequesting - Print "REQUESTING" and exit
To help keep AI open, this project migrated to GPL starting from v0.3.0.























