AgenticChatTemplate 使用说明[Beta]

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

基本介绍

AgenticChatTemplate 是面向 *schema.AgenticMessage 的 Prompt 组件抽象,用于把 map[string]any 中的变量填充到 agentic message 模板中,并输出 []*schema.AgenticMessageAgenticModel 或后续编排节点使用。

它与已有 ChatTemplate 的设计基本一致,但消息类型从 *schema.Message 切换为 *schema.AgenticMessage,并且模板渲染只作用于用户输入类内容块。

组件定义

代码位置:components/prompt/interface.go

type AgenticChatTemplate interface {
    Format(ctx context.Context, vs map[string]any, opts ...Option) ([]*schema.AgenticMessage, error)
}

Format 参数说明:

参数说明
ctx
请求上下文,也承载 callback manager 等运行时信息
vs
模板变量表,key 为占位符名称,value 为实际值
opts
Prompt 组件 Option,支持实现侧自定义扩展

返回值:

返回值说明
[]*schema.AgenticMessage
渲染后的 agentic message 列表
error
缺少变量、变量类型不匹配或模板渲染失败时返回错误

构造方式

FromAgenticMessages

代码位置:components/prompt/agentic_chat_template.go

func FromAgenticMessages(formatType schema.FormatType, templates ...schema.AgenticMessagesTemplate) *DefaultAgenticChatTemplate

FromAgenticMessages 不返回 error。它接收模板格式和一组 schema.AgenticMessagesTemplate,返回默认实现 *DefaultAgenticChatTemplate

template := prompt.FromAgenticMessages(schema.FString,
    schema.SystemAgenticMessage("You are a {role}."),
    schema.AgenticMessagesPlaceholder("history", true),
    schema.UserAgenticMessage("Please help me {task}."),
)

支持的 FormatType

格式常量占位符示例适用场景
FString
schema.FString
{role}
简单变量替换
GoTemplate
schema.GoTemplate
{{.role}}
需要 Go
text/template
能力的场景
Jinja2
schema.Jinja2
{{ role }}
需要 Jinja2 语法的场景

AgenticMessagesTemplate

代码位置:schema/agentic_message.go

type AgenticMessagesTemplate interface {
    Format(ctx context.Context, vs map[string]any, formatType FormatType) ([]*AgenticMessage, error)
}

当前常用实现包括:

构造方式说明
&schema.AgenticMessage{...}
AgenticMessage
自身实现了
AgenticMessagesTemplate
schema.SystemAgenticMessage(text)
构造
system
role 消息
schema.UserAgenticMessage(text)
构造
user
role 消息
schema.AgenticMessagesPlaceholder(key, optional)
从变量表中插入一组历史 agentic messages

模板渲染范围

AgenticMessage.Format 只格式化用户输入类 block:

  • ContentBlockTypeUserInputText
  • ContentBlockTypeUserInputImage
  • ContentBlockTypeUserInputAudio
  • ContentBlockTypeUserInputVideo
  • ContentBlockTypeUserInputFile

模型输出、reasoning、tool call、tool result、MCP 和 server tool 相关 block 不作为 prompt 模板内容渲染。

💡 推荐用 schema.SystemAgenticMessageschema.UserAgenticMessageschema.NewContentBlock 构造模板,避免手动设置 ContentBlock.Type 时与内容字段不一致。

Placeholder

代码位置:schema/agentic_message.go

func AgenticMessagesPlaceholder(key string, optional bool) AgenticMessagesTemplate

行为规则:

场景行为
vs[key]
存在且类型为
[]*schema.AgenticMessage
原样插入该消息列表
vs[key]
不存在且
optional=true
返回空切片,不报错
vs[key]
不存在且
optional=false
返回错误
vs[key]
类型不是
[]*schema.AgenticMessage
返回错误

示例:

history := []*schema.AgenticMessage{
    schema.UserAgenticMessage("What is oil painting?"),
    {
        Role: schema.AgenticRoleTypeAssistant,
        ContentBlocks: []*schema.ContentBlock{
            schema.NewContentBlock(&schema.AssistantGenText{Text: "Oil painting is ..."}),
        },
    },
}

messages, err := template.Format(ctx, map[string]any{
    "role":    "professional assistant",
    "task":    "write a short poem",
    "history": history,
})
if err != nil {
    return err
}

单独使用

template := prompt.FromAgenticMessages(schema.FString,
    schema.SystemAgenticMessage("You are a {role}."),
    schema.AgenticMessagesPlaceholder("history", true),
    schema.UserAgenticMessage("Please help me {task}."),
)

messages, err := template.Format(ctx, map[string]any{
    "role": "concise assistant",
    "task": "summarize the following requirement",
    "history": []*schema.AgenticMessage{
        schema.UserAgenticMessage("Previous question"),
    },
})
if err != nil {
    return err
}

在编排中使用

Chain

代码位置:compose/chain.go

func (c *Chain[I, O]) AppendAgenticChatTemplate(node prompt.AgenticChatTemplate, opts ...GraphAddNodeOpt) *Chain[I, O]
chain := compose.NewChain[map[string]any, *schema.AgenticMessage]()
chain.AppendAgenticChatTemplate(template)
chain.AppendAgenticModel(model)

Graph

代码位置:compose/graph.go

func (g *graph) AddAgenticChatTemplateNode(key string, node prompt.AgenticChatTemplate, opts ...GraphAddNodeOpt) error
graph := compose.NewGraph[map[string]any, *schema.AgenticMessage]()
err := graph.AddAgenticChatTemplateNode("prompt", template)
if err != nil {
    return err
}

Workflow

代码位置:compose/workflow.go

func (wf *Workflow[I, O]) AddAgenticChatTemplateNode(key string, chatTemplate prompt.AgenticChatTemplate, opts ...GraphAddNodeOpt) *WorkflowNode

Parallel 与 ChainBranch

Agentic prompt 也可以放入 ParallelChainBranch

func (p *Parallel) AddAgenticChatTemplate(outputKey string, node prompt.AgenticChatTemplate, opts ...GraphAddNodeOpt) *Parallel

func (cb *ChainBranch) AddAgenticChatTemplate(key string, node prompt.AgenticChatTemplate, opts ...GraphAddNodeOpt) *ChainBranch

从前驱节点获取变量

AgenticChatTemplate.Format 需要 map[string]any。如果前驱节点输出不是 map,可以在加节点时使用 compose.WithOutputKey 把输出包装为单字段 map。

graph.AddLambdaNode("query",
    compose.InvokableLambda(func(ctx context.Context, input string) (string, error) {
        return input, nil
    }),
    compose.WithOutputKey("task"),
)

graph.AddAgenticChatTemplateNode("prompt", template)

包装后的 map 形如:

map[string]any{
    "task": previousNodeOutput,
}

Callback

组件级 callback payload

代码位置:components/prompt/agentic_callback_extra.go

type AgenticCallbackInput struct {
    Variables map[string]any
    Templates []schema.AgenticMessagesTemplate
    Extra     map[string]any
}

type AgenticCallbackOutput struct {
    Result    []*schema.AgenticMessage
    Templates []schema.AgenticMessagesTemplate
    Extra     map[string]any
}

func ConvAgenticCallbackInput(src callbacks.CallbackInput) *AgenticCallbackInput
func ConvAgenticCallbackOutput(src callbacks.CallbackOutput) *AgenticCallbackOutput

DefaultAgenticChatTemplate.Format 会在开始和结束时触发 callback,并传递上述 agentic payload。

utils/callbacks helper

代码位置:utils/callbacks/template.go

当前 AgenticPromptCallbackHandler 的公开签名如下:

type AgenticPromptCallbackHandler struct {
    OnStart func(ctx context.Context, runInfo *callbacks.RunInfo, input *prompt.CallbackInput) context.Context
    OnEnd   func(ctx context.Context, runInfo *callbacks.RunInfo, output *prompt.CallbackOutput) context.Context
    OnError func(ctx context.Context, runInfo *callbacks.RunInfo, err error) context.Context
}

使用 helper 注册:

handler := callbackHelper.NewHandlerHelper().
    AgenticPrompt(&callbackHelper.AgenticPromptCallbackHandler{
        OnStart: func(ctx context.Context, info *callbacks.RunInfo, input *prompt.CallbackInput) context.Context {
            if input != nil {
                fmt.Printf("variables: %v\n", input.Variables)
            }
            return ctx
        },
        OnError: func(ctx context.Context, info *callbacks.RunInfo, err error) context.Context {
            fmt.Printf("prompt error: %v\n", err)
            return ctx
        },
    }).
    Handler()

result, err := runnable.Invoke(ctx, variables, compose.WithCallbacks(handler))

💡 如果需要直接处理 *prompt.AgenticCallbackInput*prompt.AgenticCallbackOutput,应使用组件级 callback payload 和 prompt.ConvAgenticCallbackInput/Outpututils/callbacks.AgenticPromptCallbackHandler 当前公开签名仍复用 prompt.CallbackInput/Output

自定义实现

实现自定义 AgenticChatTemplate 只需要满足接口:

type MyAgenticPrompt struct {
    templates  []schema.AgenticMessagesTemplate
    formatType schema.FormatType
}

func (p *MyAgenticPrompt) Format(ctx context.Context, vs map[string]any, opts ...prompt.Option) ([]*schema.AgenticMessage, error) {
    result := make([]*schema.AgenticMessage, 0, len(p.templates))
    for _, tpl := range p.templates {
        msgs, err := tpl.Format(ctx, vs, p.formatType)
        if err != nil {
            return nil, err
        }
        result = append(result, msgs...)
    }
    return result, nil
}

如需支持自定义 option,可通过 prompt.WrapImplSpecificOptFnprompt.GetImplSpecificOptions 实现。

使用建议

  • FromAgenticMessages 不返回 error,示例中不应写成 template, err := ...
  • AgenticMessagesPlaceholder 的变量值必须是 []*schema.AgenticMessage
  • 模板变量命名应稳定一致,缺失变量会在运行时返回错误。
  • 对历史对话使用 AgenticMessagesPlaceholder("history", true),可以在无历史时自然返回空列表。
  • 在 Graph/Chain 中,确保 Agentic prompt 后接收的是 []*schema.AgenticMessage 类型的节点,例如 AgenticModel