AgenticModel 使用说明[Beta]

💡 本功能在 v0.9 版本开始提供。本文以当前 main 分支源码为准,代码位置主要包括 components/model/interface.gocomponents/model/option.goschema/agentic_message.go

基本介绍

AgenticModel 是 Eino 面向 agentic provider API 的模型组件抽象。它使用 *schema.AgenticMessage 作为消息载体,通过有序的 ContentBlock 表达文本、reasoning、多模态内容、函数工具调用、服务端内置工具调用、MCP 工具调用和审批结果。

与传统 ChatModel 相比,AgenticModel 更适合直接承接 OpenAI Responses API、Claude API、Gemini API 等 provider 原生的 agentic 能力:一次模型请求中可能包含多段 reasoning、多次工具调用、服务端工具结果或 MCP 审批信息。Eino 不再把这些内容压平成单一文本字段,而是保留为结构化块。

与 ChatModel 的关系

维度AgenticModelChatModel
基础接口
model.BaseModel[*schema.AgenticMessage]
model.BaseModel[*schema.Message]
类型别名
type AgenticModel = BaseModel[*schema.AgenticMessage]
type BaseChatModel = BaseModel[*schema.Message]
消息结构
AgenticMessage.ContentBlocks
Message.Content
ToolCalls
ToolCallID
等字段
工具绑定调用时通过
model.WithTools(...)
model.WithAgenticToolChoice(...)
传入
ToolCallingChatModel.WithTools(...)
或调用时 Option
表达能力reasoning、多模态输入输出、function tool、server tool、MCP tool、approval传统 chat completion 消息与 tool call
下游执行器
compose.AgenticToolsNode
compose.ToolsNode

💡 AgenticModel 没有 WithTools 方法。WithToolsToolCallingChatModel 的实例方法;agentic 路径的工具信息通过 model.WithTools(tools) 作为请求级 Option 传入。

组件定义

BaseModel 与 AgenticModel

代码位置: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 阻塞直到模型返回完整响应。

Generate(ctx context.Context, input []*schema.AgenticMessage, opts ...model.Option) (*schema.AgenticMessage, error)

参数说明:

参数说明
ctx
请求上下文,也承载 callback manager 等运行时信息
input
按时间顺序排列的 agentic message 列表
opts
请求级模型配置,例如温度、工具、tool choice、模型名等

Stream

Stream 返回增量消息流。调用方负责读取并关闭 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.StreamReader 只能消费一次。如需多个消费者读取同一个流,应在读取前复制 reader,而不是在消费后复用。

请求级 Option

代码位置:components/model/option.go

Option适用范围说明
model.WithTools(tools)
通用,agentic 路径常用设置本次请求可被模型调用的工具定义;
nil
会被规范化为空切片
model.WithDeferredTools(tools)
AgenticModel注册可被模型内置 tool search 延迟加载的工具;不要同时放入
WithTools
model.WithToolSearchTool(tool)
AgenticModel注册模型用于检索 deferred tools 的 tool search 工具;不要放入
WithTools
model.WithAgenticToolChoice(choice)
AgenticModel控制 agentic 模型如何选择 function/MCP/server tool
model.WithToolChoice(choice, names...)
ChatModel仅适用于 ChatModel 的 tool choice

AgenticToolChoice 定义在 schema/tool.go

type AgenticToolChoice struct {
    Type    ToolChoice
    Allowed *AgenticAllowedToolChoice
    Forced  *AgenticForcedToolChoice
}

type AllowedTool struct {
    FunctionName string
    MCPTool      *AllowedMCPTool
    ServerTool   *AllowedServerTool
}

AgenticMessage

代码位置: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 只有 systemuserassistant 三类 role。工具调用和工具结果不是独立 role,而是由 ContentBlock 表达。

ResponseMeta

type AgenticResponseMeta struct {
    TokenUsage      *TokenUsage
    OpenAIExtension *openai.ResponseMetaExtension
    GeminiExtension *gemini.ResponseMetaExtension
    ClaudeExtension *claude.ResponseMetaExtension
    Extension       any
}

TokenUsage 是通用 token 统计;OpenAI、Gemini、Claude 的 provider 扩展使用专门字段;其他模型实现可以放入 Extension

ContentBlock

ContentBlockAgenticMessage 的最小内容单元。一个 message 可以包含多个有序 block,用于表达一次响应中的多段 reasoning、文本、多模态输出和工具事件。

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
}
类型常量对应字段说明
reasoning
ContentBlockTypeReasoning
Reasoning
模型 reasoning 摘要或原始 reasoning 文本
用户输入
ContentBlockTypeUserInputText/Image/Audio/Video/File
UserInput*
用户侧文本与多模态输入
模型输出
ContentBlockTypeAssistantGenText/Image/Audio/Video
AssistantGen*
模型生成的文本或多模态内容
函数工具调用
ContentBlockTypeFunctionToolCall
FunctionToolCall
provider 生成的本地 function tool call
函数工具结果
ContentBlockTypeFunctionToolResult
FunctionToolResult
用户侧执行 function tool 后返回给模型的结果
tool search 结果
ContentBlockTypeToolSearchResult
ToolSearchFunctionToolResult
客户端 tool search 发现并加载的工具定义
服务端工具
ContentBlockTypeServerToolCall/Result
ServerToolCall/Result
provider 服务端执行的内置工具,例如 web search
MCP 工具
ContentBlockTypeMCPToolCall/Result/ListToolsResult
MCP*
provider 侧托管的 MCP 工具调用、结果与工具列表
MCP 审批
ContentBlockTypeMCPToolApprovalRequest/Response
MCPToolApproval*
MCP 工具执行前的人类审批请求和响应

💡 当前 ToolSearchFunctionToolResult 字段的 JSON tag 是 tool_search_function_tool_result,但 ContentBlockTypeToolSearchResult 的字符串值是 tool_search_result。文档和业务逻辑应以源码定义为准。

常用内容结构

Reasoning

type Reasoning struct {
    Text      string
    Signature string
}

Signature 用于某些 provider 的加密 reasoning token 回传场景。

用户输入内容

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
}

UserInputAudioUserInputVideo 同样支持 URLBase64DataMIMEType

模型生成内容

type AssistantGenText struct {
    Text            string
    OpenAIExtension *openai.AssistantGenTextExtension
    ClaudeExtension *claude.AssistantGenTextExtension
    Extension       any
}

AssistantGenImageAssistantGenAudioAssistantGenVideo 支持 URLBase64DataMIMEType

Function tool call

type FunctionToolCall struct {
    CallID    string
    Name      string
    Arguments string
}

Arguments 是 JSON 字符串,由模型生成并交给 AgenticToolsNode 执行。

Function tool result

当前实现中,FunctionToolResult 不再使用 Result string,而是使用 Content []*FunctionToolResultContentBlock,以统一承载文本和多模态工具结果。

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 tool 由模型服务端执行,ArgumentsContent 的具体结构由组件实现和 provider 协议决定。

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 审批相关结构:

type MCPToolApprovalRequest struct {
    ID          string
    Name        string
    Arguments   string
    ServerLabel string
}

type MCPToolApprovalResponse struct {
    ApprovalRequestID string
    Approve           bool
    Reason            string
}

构造辅助函数

快捷消息

msg := schema.SystemAgenticMessage("You are a helpful assistant.")
msg := schema.UserAgenticMessage("Analyze this file.")

SystemAgenticMessageUserAgenticMessage 都会创建一个带 UserInputText block 的 AgenticMessage

NewContentBlock

block := schema.NewContentBlock(&schema.AssistantGenText{
    Text: "done",
})

chunk := schema.NewContentBlockChunk(
    &schema.AssistantGenText{Text: "partial"},
    &schema.StreamingMeta{Index: 0},
)

NewContentBlock 会根据传入的具体内容类型自动设置 ContentBlock.Type 与对应字段;不支持的类型会返回 nil

与 AgenticToolsNode 的协作

AgenticModel 生成本地函数工具调用时,会在 assistant message 中产生 FunctionToolCall block。compose.AgenticToolsNode 会读取这些 block,执行对应 tool.BaseTool,再把结果转换成 role 为 userFunctionToolResult block 返回给模型。

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)

输出结构示意:

&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"},
                },
            },
        }),
    },
}

最小调用示例

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)
    }
}

使用建议

  • 优先使用 schema.NewContentBlock 构造 block,避免 Type 与内容字段不一致。
  • 工具结果应使用 FunctionToolResult.Content 表达,避免把多模态结果压平成字符串。
  • Provider 专属响应信息应放入对应扩展字段或 Extension,不要写入主结构的通用字段。
  • 流式输出中可以通过 StreamingMeta.Index 表示当前 chunk 对应最终响应中的 block 索引。
  • 文档和业务代码中不要假设存在 tool role;agentic 路径的工具事件由 ContentBlock 承载。