Toolset
I toolset sono collezioni di tool che gli agenti possono usare. Goa-AI supporta diversi tipi di toolset, ciascuno con diversi modelli di esecuzione e casi d’uso.
Tipi di Toolset
Toolset Service-Owned (Method-Backed)
Dichiarati tramite Toolset("name", func() { ... }); i tool possono BindTo metodi di servizio Goa o essere implementati da executor custom.
- Il codegen emette spec/tipi/codec per-toolset sotto
gen/<service>/tools/<toolset>/ - Gli agenti che
Usequesti toolset importano le spec del provider e ottengono call builder ed executor factory tipizzati - Le applicazioni registrano executor che decodificano arg tipizzati (tramite codec forniti dal runtime), usano opzionalmente trasformazioni, chiamano client del servizio e restituiscono
ToolResult
Toolset Agent-Implemented (Agent-as-Tool)
Definiti in un blocco Export dell’agente, e opzionalmente Useati da altri agenti.
- La proprietà resta al servizio; l’agente è l’implementazione
- Il codegen emette helper
agenttools/<toolset>lato provider conNewRegistratione call builder tipizzati - Gli helper lato consumer negli agenti che
Useil toolset esportato delegano agli helper del provider mantenendo i metadati di routing centralizzati - L’esecuzione avviene inline; i payload vengono passati come JSON canonico e decodificati solo al confine se necessario per i prompt
Toolset MCP
Dichiarati tramite MCPToolset(service, suite) e referenziati tramite Use(MCPToolset(...)).
- La registrazione generata imposta
DecodeInExecutor=truecosì il JSON raw viene passato all’executor MCP - L’executor MCP decodifica usando i propri codec
- I wrapper generati gestiscono schemi/encoder JSON e trasporti (HTTP/SSE/stdio) con retry e tracing
Modelli di Esecuzione
Esecuzione Basata su Attività (Default)
I toolset service-backed eseguono tramite attività Temporal (o equivalente in altri engine):
- Il planner restituisce chiamate tool in
PlanResult(il payload èjson.RawMessage) - Il runtime schedula
ExecuteToolActivityper ogni chiamata tool - L’attività decodifica il payload tramite codec generato per validazione/hint
- Chiama
Execute(ctx, planner.ToolRequest)della registrazione del toolset con JSON canonico - Re-codifica il risultato con il codec del risultato generato
Esecuzione Inline (Agent-as-Tool)
I toolset agent-as-tool eseguono inline dalla prospettiva del planner mentre il runtime esegue l’agente provider come un vero child run:
- Il runtime rileva
Inline=truesulla registrazione del toolset. - Inietta il
engine.WorkflowContextinctxcosì la funzioneExecutedel toolset può avviare l’agente provider come child workflow con il proprioRunID. - Chiama
Execute(ctx, call)del toolset con payload JSON canonico e metadati del tool (inclusiRunIDeToolCallIDdel padre). - L’executor agent-tool generato costruisce messaggi agente annidati (system + user) dal payload del tool ed esegue l’agente provider come child run usando helper del runtime.
- L’agente annidato esegue un loop plan/execute/resume completo nel proprio run; il suo
RunOutpute gli eventi tool vengono aggregati in unplanner.ToolResultpadre che porta il payload risultato, telemetria aggregata,ChildrenCountdel child, e unRunLinkche punta al child run. - I subscriber dello stream emettono sia
tool_start/tool_endper la chiamata tool padre che un evento linkagent_run_startedcosì UI e debugger possono agganciarsi allo stream del child run su richiesta.
Modello Executor-First
I toolset di servizio generati espongono un singolo costruttore generico:
New<Agent><Toolset>ToolsetRegistration(exec runtime.ToolCallExecutor)
Le applicazioni registrano un’implementazione executor per ogni toolset consumato. L’executor decide come eseguire il tool (client del servizio, MCP, agente annidato, ecc.) e riceve metadati espliciti per-call tramite ToolCallMeta.
Esempio Executor
func Execute(ctx context.Context, meta runtime.ToolCallMeta, call planner.ToolRequest) (planner.ToolResult, error) {
switch call.Name {
case "orchestrator.profiles.upsert":
args, err := profilesspecs.UnmarshalUpsertPayload(call.Payload)
if err != nil {
return planner.ToolResult{
Error: planner.NewToolError("invalid payload"),
}, nil
}
// Trasformazioni opzionali se emesse dal codegen
mp, _ := profilesspecs.ToMethodPayload_Upsert(args)
methodRes, err := client.Upsert(ctx, mp)
if err != nil {
return planner.ToolResult{
Error: planner.ToolErrorFromError(err),
}, nil
}
tr, _ := profilesspecs.ToToolReturn_Upsert(methodRes)
return planner.ToolResult{Payload: tr}, nil
default:
return planner.ToolResult{
Error: planner.NewToolError("unknown tool"),
}, nil
}
}
Trasformazioni
Quando un tool è legato a un metodo Goa tramite BindTo, la generazione del codice analizza l’Arg/Return del tool e il Payload/Result del metodo. Se le forme sono compatibili, Goa emette helper di trasformazione type-safe:
ToMethodPayload_<Tool>(in <ToolArgs>) (<MethodPayload>, error)ToToolReturn_<Tool>(in <MethodResult>) (<ToolReturn>, error)
Le trasformazioni vengono emesse sotto gen/<service>/agents/<agent>/specs/<toolset>/transforms.go e usano GoTransform di Goa per mappare i campi in sicurezza. Se una trasformazione non viene emessa, scrivi un mapper esplicito nell’executor.
Identità del Tool
Ogni toolset definisce identificatori tool tipizzati (tools.Ident) per tutti i tool generati—inclusi i toolset non esportati. Preferisci queste costanti a stringhe ad-hoc:
import chattools "example.com/assistant/gen/orchestrator/agents/chat/agenttools/search"
// Usa una costante generata invece di stringhe/cast ad-hoc
spec, _ := rt.ToolSpec(chattools.Search)
schemas, _ := rt.ToolSchema(chattools.Search)
Per i toolset esportati (agent-as-tool), Goa-AI genera anche package agenttools con:
- costanti ID tool tipizzate,
- tipi alias payload/result,
- codec,
- e helper builder come
New<Search>Call.
Usa questi helper nei planner e nel codice runtime/introspezione per evitare ID tipizzati a stringa e mantenere i tuoi riferimenti tool allineati con il design.
Semantiche di Decode & Validazione
Goa-AI usa un contratto JSON canonico per i payload dei tool:
- Planner: Passano sempre
json.RawMessageinToolRequest.Payload. I planner non hanno bisogno di decodificare gli argomenti tool in struct tipizzate. - Runtime: Gestisce tutta la decodifica schema-aware. Decodifica payload JSON in struct tipizzate per validazione, retry hint e rendering prompt agent-as-tool.
- Executor: Ricevono il JSON canonico. Possono usare codec generati per decodificare in struct tipizzate per la logica di implementazione.
La validazione stretta resta al confine del servizio (servizio Goa). Gli errori di validazione restituiti dai servizi possono essere mappati a RetryHint se scegli di mostrare guide recuperabili ai planner.
Prossimi Passi
- Impara l’Integrazione MCP per suite di tool esterni
- Esplora la Composizione Agenti per pattern agent-as-tool
- Leggi i Concetti Runtime per capire il flusso di esecuzione dei tool