This package provides utilities for wrapping Eino's composition types (compose.Graph, compose.Chain, compose.Workflow) as agent tools. It enables you to expose complex multi-step processing pipelines as single tools that can be used by ChatModelAgent.
Overview
The package provides two main tool types:
| Tool Type |
Interface |
Use Case |
InvokableGraphTool |
tool.InvokableTool |
Standard request-response tools |
StreamableGraphTool |
tool.StreamableTool |
Tools that stream output incrementally |
Both tools support:
- Any
Compilable type (compose.Graph, compose.Chain, compose.Workflow)
- Interrupt/Resume for human-in-the-loop workflows
- Checkpoint-based state persistence
Installation
import "github.com/cloudwego/eino-examples/adk/common/tool/graphtool"
Quick Start
Wrap a composition as a standard invokable tool:
// Define input/output types
type MyInput struct {
Query string `json:"query" jsonschema_description:"The query to process"`
}
type MyOutput struct {
Result string `json:"result"`
}
// Create a chain/graph/workflow
chain := compose.NewChain[*MyInput, *MyOutput]()
chain.AppendLambda(compose.InvokableLambda(func(ctx context.Context, input *MyInput) (*MyOutput, error) {
return &MyOutput{Result: "Processed: " + input.Query}, nil
}))
// Wrap as tool
tool, err := graphtool.NewInvokableGraphTool[*MyInput, *MyOutput](
chain,
"my_tool",
"Description of what this tool does",
)
Wrap a composition as a streaming tool (useful when the final node streams output):
// Graph that outputs streaming messages
graph := compose.NewGraph[*MyInput, *schema.Message]()
graph.AddChatModelNode("llm", chatModel)
// ... add edges ...
// Wrap as streaming tool
tool, err := graphtool.NewStreamableGraphTool[*MyInput, *schema.Message](
graph,
"streaming_tool",
"A tool that streams its response",
)
// Use with ReturnDirectly for direct streaming to user
agent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
// ...
ToolsConfig: adk.ToolsConfig{
ToolsNodeConfig: compose.ToolsNodeConfig{
Tools: []tool.BaseTool{tool},
},
ReturnDirectly: map[string]bool{
"streaming_tool": true,
},
},
})
Compilable Interface
Both tool types accept any type implementing the Compilable interface:
type Compilable[I, O any] interface {
Compile(ctx context.Context, opts ...compose.GraphCompileOption) (compose.Runnable[I, O], error)
}
This includes:
compose.Graph[I, O]
compose.Chain[I, O]
compose.Workflow[I, O]
Interrupt/Resume Support
GraphTools fully support Eino's interrupt/resume mechanism for human-in-the-loop workflows:
// Inside a workflow node
if needsApproval {
return nil, compose.StatefulInterrupt(ctx, &ApprovalInfo{
Message: "Approval required",
}, currentState)
}
The tool automatically:
- Captures checkpoint state when interrupted
- Wraps the interrupt with
CompositeInterrupt for proper propagation
- Restores state and resumes execution when
runner.ResumeWithParams is called
GraphTools implement standard tool.InvokableTool or tool.StreamableTool interfaces, making them compatible with any tool wrapper in the ecosystem. Examples of wrappers you can use:
InvokableApprovableTool: Adds human approval before tool execution
InvokableReviewEditTool: Allows users to review and edit tool arguments
FollowUpTool: Asks users follow-up questions during execution
- Custom wrappers you create
Nested Interrupts
When a GraphTool with internal interrupts is wrapped by another interrupt-based wrapper (e.g., InvokableApprovableTool), both interrupt layers work independently:
- Outer interrupt: Wrapper-level interrupt (e.g., approval via
InvokableApprovableTool)
- Inner interrupt: Workflow-level interrupt (via
StatefulInterrupt inside graph nodes)
This works because each layer uses distinct interrupt state types, preventing conflicts.
Pass compose options to the underlying runnable:
result, err := tool.InvokableRun(ctx, argsJSON,
graphtool.WithGraphToolOption(
compose.WithCallbacks(myCallback),
),
)
Examples
See the examples directory for complete working examples:
API Reference
func NewInvokableGraphTool[I, O any](
compilable Compilable[I, O],
name, desc string,
opts ...compose.GraphCompileOption,
) (*InvokableGraphTool[I, O], error)
Creates a new invokable tool from a compilable composition.
func NewStreamableGraphTool[I, O any](
compilable Compilable[I, O],
name, desc string,
opts ...compose.GraphCompileOption,
) (*StreamableGraphTool[I, O], error)
Creates a new streaming tool from a compilable composition.
func WithGraphToolOption(opts ...compose.Option) tool.Option
Wraps compose options as tool options for passing to InvokableRun or StreamableRun.