Runner provides the interface to run Agents, responsible for session management and event stream processing. The core responsibilities of Runner are: obtain or create sessions, generate an Invocation ID, call Agent.Run, process the returned event stream, and append non-partial response events to the session.
🎯 Key Features
💾 Session Management: Obtain/create sessions via sessionService, using inmemory.NewSessionService() by default.
🔄 Event Handling: Receive Agent event streams and append non-partial response events to the session.
🆔 ID Generation: Automatically generate Invocation IDs and event IDs.
📊 Observability Integration: Integrates telemetry/trace to automatically record spans.
✅ Completion Event: Generates a runner-completion event after the Agent event stream ends.
# Enter the example directory.cdexamples/runner
# Set API key.exportOPENAI_API_KEY="your-api-key"# Basic run.gorunmain.go
# Use Redis session.dockerrun-d-p6379:6379redis:alpine
gorunmain.go-sessionredis
# Custom model.gorunmain.go-model"gpt-4o-mini"
💬 Interactive Features
After running the example, the following special commands are supported:
/history - Ask AI to show conversation history.
/new - Start a new session (reset conversation context).
/exit - End the conversation.
When the AI uses tools, detailed invocation processes will be displayed:
// Execute a single conversation.eventChan,err:=r.Run(ctx,userID,sessionID,message,options...)// With run options (currently RunOptions is an empty struct, reserved for future use).eventChan,err:=r.Run(ctx,userID,sessionID,message)
// Configuration options supported by Redis.sessionService,err:=redis.NewService(redis.WithRedisClientURL("redis://localhost:6379"),redis.WithSessionEventLimit(1000),// Limit number of session events.// redis.WithRedisInstance("redis-instance"), // Or use an instance name.)
🤖 Agent Configuration
Runner's core responsibility is to manage the Agent execution flow. A created Agent needs to be executed via Runner.
// Create a basic Agent (see agent.md for detailed configuration).agent:=llmagent.New("assistant",llmagent.WithModel(model),llmagent.WithInstruction("You are a helpful AI assistant."))// Execute Agent with Runner.r:=runner.NewRunner("my-app",agent)
Generation Configuration
Runner passes generation configuration to the Agent:
// Create tools (see tool.md for detailed configuration).tools:=[]tool.Tool{function.NewFunctionTool(myFunction,function.WithName("my_tool")),// More tools...}// Add tools to the Agent.agent:=llmagent.New("assistant",llmagent.WithModel(model),llmagent.WithTools(tools))// Runner runs the Agent configured with tools.r:=runner.NewRunner("my-app",agent)
Tool invocation flow: Runner itself does not directly handle tool invocation. The flow is as follows:
Pass tools: Runner passes context to the Agent via Invocation.
Agent processing: Agent.Run handles the tool invocation logic.
Event forwarding: Runner receives the event stream returned by the Agent and forwards it.
Session recording: Append non-partial response events to the session.
Multi-Agent Support
Runner can execute complex multi-Agent structures (see multiagent.md for details):
import"trpc.group/trpc-go/trpc-agent-go/agent/chainagent"// Create a multi-Agent pipeline.multiAgent:=chainagent.New("pipeline",chainagent.WithSubAgents([]agent.Agent{agent1,agent2}))// Execute with the same Runner.r:=runner.NewRunner("multi-app",multiAgent)
// The Invocation created by Runner contains the following fields.invocation:=&agent.Invocation{Agent:r.agent,// Agent instance.Session:sess,// Session object.InvocationID:invocationID,// Unique identifier.EndInvocation:false,// End flag.Message:message,// User message.RunOptions:ro,// Run options.EventCompletionCh:eventCompletionCh,// Event completion channel.// Note: Invocation also includes other fields such as AgentName, Branch, Model,// TransferInfo, AgentCallbacks, ModelCallbacks, ToolCallbacks, etc.,// but these fields are used and managed internally by the Agent.}
// Handle errors from Runner.Run.eventChan,err:=r.Run(ctx,userID,sessionID,message)iferr!=nil{log.Printf("Runner execution failed: %v",err)returnerr}// Handle errors in the event stream.forevent:=rangeeventChan{ifevent.Error!=nil{log.Printf("Event error: %s",event.Error.Message)continue}// Handle normal events.}
// Use context to control lifecycle.ctx,cancel:=context.WithCancel(context.Background())defercancel()// Ensure all events are consumed.eventChan,err:=r.Run(ctx,userID,sessionID,message)iferr!=nil{returnerr}forevent:=rangeeventChan{// Process events.ifevent.Done{break}}
import("context""fmt""trpc.group/trpc-go/trpc-agent-go/model""trpc.group/trpc-go/trpc-agent-go/runner")// Check whether Runner works properly.funccheckRunner(rrunner.Runner,ctxcontext.Context)error{testMessage:=model.NewUserMessage("test")eventChan,err:=r.Run(ctx,"test-user","test-session",testMessage)iferr!=nil{returnfmt.Errorf("Runner.Run failed: %v",err)}// Check the event stream.forevent:=rangeeventChan{ifevent.Error!=nil{returnfmt.Errorf("Received error event: %s",event.Error.Message)}ifevent.Done{break}}returnnil}
📝 Summary
The Runner component is a core part of the tRPC-Agent-Go framework, providing complete conversation management and Agent orchestration capabilities. By properly using session management, tool integration, and event handling, you can build powerful intelligent conversational applications.