AgenticModel User Guide [Beta]
💡 This feature is available starting from v0.9. This document is based on the current main branch source code, with code primarily located in
components/model/interface.go,components/model/option.go, andschema/agentic_message.go.
Introduction
AgenticModel is Eino’s model component abstraction for agentic provider APIs. It uses *schema.AgenticMessage as the message carrier and represents text, reasoning, multimodal content, function tool calls, server-side built-in tool calls, MCP tool calls, and approval results through ordered ContentBlocks.
Compared to the traditional ChatModel, AgenticModel is more suitable for directly leveraging the native agentic capabilities of provider APIs such as OpenAI Responses API, Claude API, and Gemini API: a single model request may contain multiple reasoning segments, multiple tool calls, server tool results, or MCP approval information. Eino no longer flattens these into a single text field but preserves them as structured blocks.
Relationship with ChatModel
| Dimension | AgenticModel | ChatModel |
| Base Interface | model.BaseModel[*schema.AgenticMessage] | model.BaseModel[*schema.Message] |
| Type Alias | type AgenticModel = BaseModel[*schema.AgenticMessage] | type BaseChatModel = BaseModel[*schema.Message] |
| Message Structure | AgenticMessage.ContentBlocks | Message.Content, ToolCalls, ToolCallID, etc. |
| Tool Binding | Passed at call time viamodel.WithTools(...), model.WithAgenticToolChoice(...) | ToolCallingChatModel.WithTools(...)or call-time Option |
| Expressiveness | reasoning, multimodal input/output, function tool, server tool, MCP tool, approval | Traditional chat completion messages and tool calls |
| Downstream Executor | compose.AgenticToolsNode | compose.ToolsNode |
💡
AgenticModeldoes not have aWithToolsmethod.WithToolsis an instance method ofToolCallingChatModel; in the agentic path, tool information is passed viamodel.WithTools(tools)as a request-level Option.
Component Definition
BaseModel and AgenticModel
Code location: components/model/interface.go
// BaseModel is the generic base model interface parameterized by message type M.
type BaseModel[M any] interface {
Generate(ctx context.Context, input []M, opts ...Option) (M, error)
Stream(ctx context.Context, input []M, opts ...Option) (*schema.StreamReader[M], error)
}
// AgenticModel is a type alias for BaseModel specialized with
// *schema.AgenticMessage.
type AgenticModel = BaseModel[*schema.AgenticMessage]
Generate
Generate blocks until the model returns a complete response.
Generate(ctx context.Context, input []*schema.AgenticMessage, opts ...model.Option) (*schema.AgenticMessage, error)
Parameter description:
| Parameter | Description |
ctx | Request context, also carries runtime information such as callback manager |
input | Chronologically ordered list of agentic messages |
opts | Request-level model configuration, such as temperature, tools, tool choice, model name, etc. |
Stream
Stream returns an incremental message stream. The caller is responsible for reading and closing the StreamReader.
Stream(ctx context.Context, input []*schema.AgenticMessage, opts ...model.Option) (*schema.StreamReader[*schema.AgenticMessage], error)
reader, err := m.Stream(ctx, messages)
if err != nil {
return err
}
defer reader.Close()
for {
chunk, err := reader.Recv()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
return err
}
// handle chunk
}
💡
schema.StreamReadercan only be consumed once. If multiple consumers need to read the same stream, the reader should be copied before reading, rather than reused after consumption.
Request-Level Options
Code location: components/model/option.go
| Option | Applicable Scope | Description |
model.WithTools(tools) | General, commonly used in agentic path | Sets the tool definitions that can be called by the model for this request;nilis normalized to an empty slice |
model.WithDeferredTools(tools) | AgenticModel | Registers tools that can be lazily loaded by the model's built-in tool search; do not also place them inWithTools |
model.WithToolSearchTool(tool) | AgenticModel | Registers the tool search tool used by the model to retrieve deferred tools; do not place it inWithTools |
model.WithAgenticToolChoice(choice) | AgenticModel | Controls how the agentic model selects function/MCP/server tools |
model.WithToolChoice(choice, names...) | ChatModel | Tool choice only applicable to ChatModel |
AgenticToolChoice is defined in schema/tool.go:
type AgenticToolChoice struct {
Type ToolChoice
Allowed *AgenticAllowedToolChoice
Forced *AgenticForcedToolChoice
}
type AllowedTool struct {
FunctionName string
MCPTool *AllowedMCPTool
ServerTool *AllowedServerTool
}
AgenticMessage
Code location: schema/agentic_message.go
type AgenticRoleType string
const (
AgenticRoleTypeSystem AgenticRoleType = "system"
AgenticRoleTypeUser AgenticRoleType = "user"
AgenticRoleTypeAssistant AgenticRoleType = "assistant"
)
type AgenticMessage struct {
Role AgenticRoleType
ContentBlocks []*ContentBlock
ResponseMeta *AgenticResponseMeta
Extra map[string]any
}
AgenticMessage only has three role types: system, user, and assistant. Tool calls and tool results are not independent roles but are expressed through ContentBlock.
ResponseMeta
type AgenticResponseMeta struct {
TokenUsage *TokenUsage
OpenAIExtension *openai.ResponseMetaExtension
GeminiExtension *gemini.ResponseMetaExtension
ClaudeExtension *claude.ResponseMetaExtension
Extension any
}
TokenUsage provides universal token statistics; OpenAI, Gemini, and Claude provider extensions use dedicated fields; other model implementations can use Extension.
ContentBlock
ContentBlock is the smallest content unit of AgenticMessage. A message can contain multiple ordered blocks to express multiple reasoning segments, text, multimodal output, and tool events within a single response.
type ContentBlock struct {
Type ContentBlockType
Reasoning *Reasoning
UserInputText *UserInputText
UserInputImage *UserInputImage
UserInputAudio *UserInputAudio
UserInputVideo *UserInputVideo
UserInputFile *UserInputFile
AssistantGenText *AssistantGenText
AssistantGenImage *AssistantGenImage
AssistantGenAudio *AssistantGenAudio
AssistantGenVideo *AssistantGenVideo
FunctionToolCall *FunctionToolCall
FunctionToolResult *FunctionToolResult
ToolSearchFunctionToolResult *ToolSearchFunctionToolResult
ServerToolCall *ServerToolCall
ServerToolResult *ServerToolResult
MCPToolCall *MCPToolCall
MCPToolResult *MCPToolResult
MCPListToolsResult *MCPListToolsResult
MCPToolApprovalRequest *MCPToolApprovalRequest
MCPToolApprovalResponse *MCPToolApprovalResponse
StreamingMeta *StreamingMeta
Extra map[string]any
}
| Type | Constant | Corresponding Field | Description |
| reasoning | ContentBlockTypeReasoning | Reasoning | Model reasoning summary or raw reasoning text |
| User Input | ContentBlockTypeUserInputText/Image/Audio/Video/File | UserInput* | User-side text and multimodal input |
| Model Output | ContentBlockTypeAssistantGenText/Image/Audio/Video | AssistantGen* | Text or multimodal content generated by the model |
| Function Tool Call | ContentBlockTypeFunctionToolCall | FunctionToolCall | Local function tool call generated by the provider |
| Function Tool Result | ContentBlockTypeFunctionToolResult | FunctionToolResult | Result returned to the model after user-side execution of a function tool |
| Tool Search Result | ContentBlockTypeToolSearchResult | ToolSearchFunctionToolResult | Tool definitions discovered and loaded by client-side tool search |
| Server Tool | ContentBlockTypeServerToolCall/Result | ServerToolCall/Result | Provider server-side executed built-in tools, e.g., web search |
| MCP Tool | ContentBlockTypeMCPToolCall/Result/ListToolsResult | MCP* | Provider-side hosted MCP tool calls, results, and tool lists |
| MCP Approval | ContentBlockTypeMCPToolApprovalRequest/Response | MCPToolApproval* | Human approval requests and responses before MCP tool execution |
💡 Currently, the JSON tag of the
ToolSearchFunctionToolResultfield istool_search_function_tool_result, but the string value ofContentBlockTypeToolSearchResultistool_search_result. Documentation and business logic should follow the source code definitions.
Common Content Structures
Reasoning
type Reasoning struct {
Text string
Signature string
}
Signature is used for scenarios where certain providers require encrypted reasoning tokens to be passed back.
User Input Content
type UserInputText struct {
Text string
}
type UserInputImage struct {
URL string
Base64Data string
MIMEType string
Detail ImageURLDetail
}
type UserInputFile struct {
URL string
Name string
Base64Data string
MIMEType string
}
UserInputAudio and UserInputVideo similarly support URL, Base64Data, and MIMEType.
Model Generated Content
type AssistantGenText struct {
Text string
OpenAIExtension *openai.AssistantGenTextExtension
ClaudeExtension *claude.AssistantGenTextExtension
Extension any
}
AssistantGenImage, AssistantGenAudio, and AssistantGenVideo support URL, Base64Data, and MIMEType.
Function tool call
type FunctionToolCall struct {
CallID string
Name string
Arguments string
}
Arguments is a JSON string generated by the model and passed to AgenticToolsNode for execution.
Function tool result
In the current implementation, FunctionToolResult no longer uses Result string but instead uses Content []*FunctionToolResultContentBlock to uniformly carry text and multimodal tool results.
type FunctionToolResult struct {
CallID string
Name string
Content []*FunctionToolResultContentBlock
}
type FunctionToolResultContentBlock struct {
Type FunctionToolResultContentBlockType
Text *UserInputText
Image *UserInputImage
Audio *UserInputAudio
Video *UserInputVideo
File *UserInputFile
Extra map[string]any
}
Server tool
type ServerToolCall struct {
Name string
CallID string
Arguments any
}
type ServerToolResult struct {
Name string
CallID string
Content any
}
Server tools are executed by the model server side. The specific structure of Arguments and Content is determined by the component implementation and provider protocol.
MCP tool
type MCPToolCall struct {
ServerLabel string
ApprovalRequestID string
CallID string
Name string
Arguments string
}
type MCPToolResult struct {
ServerLabel string
CallID string
Name string
Content string
Error *MCPToolCallError
}
MCP approval-related structures:
type MCPToolApprovalRequest struct {
ID string
Name string
Arguments string
ServerLabel string
}
type MCPToolApprovalResponse struct {
ApprovalRequestID string
Approve bool
Reason string
}
Helper Functions
Shortcut Messages
msg := schema.SystemAgenticMessage("You are a helpful assistant.")
msg := schema.UserAgenticMessage("Analyze this file.")
Both SystemAgenticMessage and UserAgenticMessage create an AgenticMessage with a UserInputText block.
NewContentBlock
block := schema.NewContentBlock(&schema.AssistantGenText{
Text: "done",
})
chunk := schema.NewContentBlockChunk(
&schema.AssistantGenText{Text: "partial"},
&schema.StreamingMeta{Index: 0},
)
NewContentBlock automatically sets the ContentBlock.Type and corresponding field based on the specific content type passed in; unsupported types return nil.
Collaboration with AgenticToolsNode
When AgenticModel generates local function tool calls, it produces FunctionToolCall blocks in the assistant message. compose.AgenticToolsNode reads these blocks, executes the corresponding tool.BaseTool, and converts the results into FunctionToolResult blocks with role user to return to the model.
input := &schema.AgenticMessage{
Role: schema.AgenticRoleTypeAssistant,
ContentBlocks: []*schema.ContentBlock{
schema.NewContentBlock(&schema.FunctionToolCall{
CallID: "call_1",
Name: "get_weather",
Arguments: `{"city":"Beijing"}`,
}),
},
}
results, err := toolsNode.Invoke(ctx, input)
Output structure illustration:
&schema.AgenticMessage{
Role: schema.AgenticRoleTypeUser,
ContentBlocks: []*schema.ContentBlock{
schema.NewContentBlock(&schema.FunctionToolResult{
CallID: "call_1",
Name: "get_weather",
Content: []*schema.FunctionToolResultContentBlock{
{
Type: schema.FunctionToolResultContentBlockTypeText,
Text: &schema.UserInputText{Text: "sunny"},
},
},
}),
},
}
Minimal Usage Example
messages := []*schema.AgenticMessage{
schema.SystemAgenticMessage("You are a concise assistant."),
schema.UserAgenticMessage("Search recent Go release notes and summarize them."),
}
resp, err := m.Generate(ctx, messages,
model.WithTools([]*schema.ToolInfo{searchToolInfo}),
model.WithAgenticToolChoice(&schema.AgenticToolChoice{
Type: schema.ToolChoiceAllowed,
}),
)
if err != nil {
return err
}
for _, block := range resp.ContentBlocks {
if block.Type == schema.ContentBlockTypeAssistantGenText && block.AssistantGenText != nil {
fmt.Println(block.AssistantGenText.Text)
}
}
Best Practices
- Prefer using
schema.NewContentBlockto construct blocks to avoid inconsistency betweenTypeand content fields. - Tool results should be expressed using
FunctionToolResult.Content; avoid flattening multimodal results into strings. - Provider-specific response information should be placed in the corresponding extension fields or
Extension; do not write them into the general fields of the main structure. - In streaming output,
StreamingMeta.Indexcan be used to indicate the block index in the final response that the current chunk corresponds to. - Do not assume a
toolrole exists in documentation and business code; tool events in the agentic path are carried byContentBlock.