Agent Collaboration

Multi-Agent Collaboration

Eino ADK provides two main Agent collaboration approaches:

Wraps a sub-Agent as a Tool, allowing the parent Agent to autonomously decide when to call it via ToolCall. The sub-Agent executes independently, and results are returned to the parent Agent’s context.

This is the most flexible and composable collaboration pattern:

  • The parent Agent retains control and can continue reasoning based on sub-Agent results
  • The sub-Agent receives an independent task description and does not inherit the parent Agent’s full conversation history
  • Multiple sub-Agents can be called in parallel
import (
    "github.com/cloudwego/eino/adk"
    "github.com/cloudwego/eino/compose"
    "github.com/cloudwego/eino/components/tool"
)

// Create sub-Agent
subAgent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
    Name:        "researcher",
    Description: "Search and summarize relevant information",
    Instruction: "You are a research assistant...",
    Model:       chatModel,
    ToolsConfig: adk.ToolsConfig{
        ToolsNodeConfig: compose.ToolsNodeConfig{
            Tools: []tool.BaseTool{searchTool},
        },
    },
})

// Wrap as Tool
agentTool := adk.NewAgentTool(ctx, subAgent)

// Parent Agent registers sub-Agent Tool
parentAgent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
    Name:        "coordinator",
    Description: "Main Agent that coordinates tasks",
    Instruction: "You are a task coordinator...",
    Model:       chatModel,
    ToolsConfig: adk.ToolsConfig{
        ToolsNodeConfig: compose.ToolsNodeConfig{
            Tools: []tool.BaseTool{agentTool},
        },
    },
})

AgentTool Options

OptionDescription
WithFullChatHistoryAsInput()
Pass the parent Agent's full conversation history as sub-Agent input (by default only the model-generated request parameters are passed)
WithAgentInputSchema(schema)
Customize the sub-Agent's input schema

Event Stream Pass-through

When ToolsConfig.EmitInternalEvents = true, the sub-Agent’s events are passed through in real-time to the parent Agent’s event stream, allowing end users to see the sub-Agent’s intermediate process.

💡 Pass-through events do not affect the parent Agent’s state or checkpoint, and are only for user display. The only exception is the Interrupted action, which propagates across boundaries via CompositeInterrupt to support interrupt recovery.

Pre-built Example: DeepAgents

DeepAgents is a best practice of the AgentAsTool pattern: the main Agent delegates subtasks to sub-Agents via TaskTool, combined with WriteTodos for task planning and progress tracking.

Workflow Agents

Deterministic orchestration for multi-step tasks with fixed processes:

TypeDescriptionConstructor
SequentialExecutes sub-Agents sequentially in array order
adk.NewSequentialAgent
ParallelExecutes all sub-Agents concurrently, finishes when all complete
adk.NewParallelAgent
LoopLoops execution of sub-Agent sequence until BreakLoop or MaxIterations exceeded
adk.NewLoopAgent

Context is passed between Workflow Agents via Transfer: the upstream Agent’s output is automatically appended to the downstream Agent’s input Messages.

Context Passing

SessionValues

Global KV store across Agents, concurrently safe for read/write by any Agent within a single run:

// Read/write API
adk.AddSessionValue(ctx, "key", value)
val, ok := adk.GetSessionValue(ctx, "key")
adk.AddSessionValues(ctx, map[string]any{"k1": v1, "k2": v2})
all := adk.GetSessionValues(ctx)

💡 SessionValues are implemented based on Context, and Runner reinitializes the Context at runtime. To inject data before running, use the WithSessionValues Option:

iter := runner.Run(ctx, messages,
    adk.WithSessionValues(map[string]any{
        "user_id": "123",
    }),
)