Graphflow

Graphflow is a Go-native Agent development framework built on a type-safe graph execution engine.
中文文档
Why Graphflow
Most Agent frameworks are Python-first, bring heavy runtimes, and blur the line between orchestration and AI logic. Graphflow is different:
|
Graphflow |
LangGraph |
Eino |
| Language |
Go |
Python |
Go |
| Core abstraction |
Graph engine |
StateGraph |
Graph + Chain |
| Config-driven |
YAML + code |
Code only |
Code only |
| Zero-dependency core |
Yes |
No |
No |
| Single binary deploy |
Yes |
No |
No |
| Built-in resilience |
Retry / CB / Bulkhead |
Limited |
Limited |
Architecture
┌──────────────────────────────────────────┐
│ Your Application │
│ Business workflows · AI Agent apps │
└─────────────────────┬────────────────────┘
│
┌─────────────────────▼────────────────────┐
│ agent/ — Agent Development Layer │
│ MessageState · LLMNode · ToolNode │
│ ReAct · RAG · Supervisor patterns │
│ ToolRegistry · Memory management │
└─────────────────────┬────────────────────┘
│ depends on
┌─────────────────────▼────────────────────┐
│ graph/ — Graph Execution Engine │
│ Graph[S] · Engine[S] · NodeFunc[S] │
│ Sequential · Conditional · Parallel │
│ Loop · Checkpoint · Hook · OTel │
│ middleware/ · node/ · checkpoint/ │
└──────────────────────────────────────────┘
The graph/ package is AI-agnostic — it works equally well for business process orchestration, ETL pipelines, and event-driven workflows. The agent/ package adds the AI-specific layer on top.
Quick Start
LLM Configuration
Graphflow uses llmgate as the LLM gateway (19 providers).
# Option 1: config file (recommended)
cp config/llmgate.toml.example config/llmgate.toml # edit your API keys
go run ./examples/agent_demo
# Option 2: environment variables
export DEEPSEEK_KEY="sk-xxx"
go run ./examples/agent_demo -env -provider deepseek
# Option 3: mock mode (no API key needed)
go run ./examples/agent_demo
ReAct Agent
Use ReActAgent.BuildGraph() for zero-boilerplate setup:
import (
"github.com/wzhongyou/graphflow/agent"
llmgate_adapter "github.com/wzhongyou/graphflow/agent/llmgate"
"github.com/wzhongyou/graphflow/graph"
"github.com/wzhongyou/llmgate/sdk"
)
gw, _ := sdk.NewFromFile("config/llmgate.toml")
adapter := llmgate_adapter.New(gw, llmgate_adapter.Config{Provider: "deepseek"})
ag := agent.NewReActAgent(agent.ReActAgentConfig{
Name: "react-agent",
LLM: adapter,
SystemPrompt: "You are a helpful assistant.",
Tools: []agent.Tool{&agent.CalculatorTool{}},
})
g, _ := ag.BuildGraph()
engine := graph.NewEngine(g)
result, _ := engine.Run(ctx, &agent.MessageState{
Messages: []agent.Message{{Role: agent.RoleUser, Content: "What is 123 * 456?"}},
}, graph.WithHook(myReactHook))
Or build the graph by hand for full control:
llm := agent.NewLLMNode(agent.LLMNodeConfig{Model: adapter, Tools: tools})
toolNode := agent.NewToolNode(tools...)
g := graph.NewGraph[*agent.MessageState]("react-agent")
g.AddNode("llm", llm.Run)
g.AddNode("tool", toolNode.Run)
g.SetEntryPoint("llm")
g.AddCondition("llm", graph.Condition[*agent.MessageState]{
If: agent.HasPendingToolCalls,
Target: "tool",
})
g.AddEdge("tool", "llm") // loop back
g.SetMaxIterations("llm", 20)
g.Compile()
Observing the ReAct loop with Hook
type reactHook struct{}
func (h *reactHook) OnNodeEnd(_ context.Context, node string, s *agent.MessageState, _ error, dur time.Duration) {
last := s.Messages[len(s.Messages)-1]
switch node {
case "llm":
if len(last.ToolCalls) > 0 {
fmt.Printf("[Thought] → Action: %s (%s)\n", last.ToolCalls[0].Name, dur)
} else {
fmt.Printf("[Thought] → Answer: %s\n", last.Content)
}
case "tool":
for _, m := range s.Messages {
if m.Role == agent.RoleTool {
fmt.Printf("[Observation] %s: %s\n", m.ToolName, m.Content)
}
}
}
}
// ... other Hook methods
Output:
[react-agent] question: What is 123 * 456?
[Thought] → Action: calculator (12ms)
[Observation] calculator: 56088
[Thought] → Answer: The answer is 56088.
[done] steps=3 duration=21ms
Business Workflow (pure graph, no AI)
g := graph.NewGraph[OrderState]("order-pipeline")
g.AddNode("validate", validateOrder)
g.AddNode("charge", chargePayment)
g.AddNode("fulfill", fulfillOrder)
g.AddNode("notify", sendNotification)
g.SetEntryPoint("validate")
g.AddEdge("validate", "charge")
g.AddEdge("charge", "fulfill")
g.AddEdge("fulfill", "notify")
g.Compile()
engine := graph.NewEngine(g)
result, err := engine.Run(ctx, initialState,
graph.WithTimeout(30*time.Second),
graph.WithCheckpoint(checkpoint.NewFileManager("/tmp/cp")),
)
Resilience Middleware
Node functions are plain func(ctx, state) (state, error) — wrap them with middleware:
// Recommended composition order (outer → inner)
node := middleware.WithRecover("payment", // panic → error
middleware.WithTimeout(chargePayment, 5*time.Second,
middleware.WithRetry(chargePayment, middleware.RetryPolicy{
MaxAttempts: 3,
Backoff: 500 * time.Millisecond,
}),
),
)
g.AddNode("charge", node)
Available middleware: WithRecover · WithTimeout · WithRetry · WithCircuitBreaker · WithRateLimit · WithBulkhead · WithValidate · WithCache
Package Layout
graphflow/
├── graph/ # Core graph engine (import "…/graph")
│ ├── graph.go # Graph[S], NodeFunc, Condition, MergeFunc
│ ├── engine.go # Engine[S].Run — Pregel superstep loop
│ ├── hooks.go # Hook[S] interface, ComposeHooks
│ ├── errors.go # Structured error types
│ ├── middleware/ # NodeFunc decorators
│ │ ├── retry.go
│ │ ├── circuitbreaker.go
│ │ ├── bulkhead.go
│ │ └── ...
│ ├── node/ # Built-in nodes (HTTP, Delay, Transform, Noop)
│ └── checkpoint/ # Persistence (memory · file · redis · sqlite)
│
├── agent/ # Agent layer (import "…/agent")
│ ├── state.go # MessageState, Message, ToolCall
│ ├── llm.go # LLMModel, Embedder, VectorStore interfaces
│ ├── nodes.go # LLMNode, ToolNode, VectorRetrieveNode, HumanInputNode
│ ├── tools.go # Tool interface, ToolRegistry, CalculatorTool
│ ├── agents.go # ReActAgent, RAGAgent, SupervisorAgent
│ ├── memory.go # ShortTermMemory, LongTermMemory
│ └── llmgate/ # llmgate adapter (LLMModel impl)
│
├── config/ # Configuration templates
│ └── llmgate.toml.example
│
└── examples/
└── agent_demo/ # ReAct agent with Hook tracing (mock + real LLM)
Roadmap
Core (graph/)
- Graph model — sequential, conditional routing
- Loop / back-edge detection with iteration limits
- Hook interface + ComposeHooks
- Resilience middleware suite
- Built-in nodes (HTTP, Delay, Transform, Noop)
- Structured error types
- Parallel fan-out / fan-in
- Stream[T] — Send / Chan / Merge / Broadcast
- Checkpoint — InMemory, File
- OTelHook
- YAML config + LoadFromFile
Agent (agent/)
- MessageState, Message, ToolCall types (A1)
- LLMModel / Embedder / VectorStore interfaces (A2)
- LLMNode, ToolNode — real implementation with tool calling (A3)
- VectorRetrieveNode, HumanInputNode (A3)
- Tool interface + ToolRegistry + CalculatorTool (A4)
- ShortTermMemory, LongTermMemory (A5)
- ReActAgent.BuildGraph (A6)
- RAGAgent.BuildGraph (A7)
- llmgate adapter — 19 providers, fallback, strategy routing
- SupervisorAgent.BuildGraph (A8)
- Stream agent + SSE (A9)
- Structured Output (A10)
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature)
- Commit your changes (
git commit -m 'Add amazing feature')
- Push and open a Pull Request
Please ensure: go vet ./... passes, new public APIs have doc comments, non-trivial logic has unit tests.
License
MIT © 2026 Wang Zhongyou