Agent Collaboration

Multi-Agent Collaboration

Eino ADK provides two primary 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 the result is 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 the sub-Agent’s result
  • 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 the 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()
Passes the parent Agent's full conversation history as the sub-Agent's input (by default, only the model-generated request parameters are passed)
WithAgentInputSchema(schema)
Customizes the sub-Agent's input schema

Event Stream Passthrough

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.

💡 Passed-through events do not affect the parent Agent’s state or checkpoint; they are for display purposes only. The only exception is the Interrupted action, which propagates across boundaries via CompositeInterrupt to support interrupt/resume.

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, completes when all finish
adk.NewParallelAgent
LoopLoops through the sub-Agent sequence until BreakLoop or MaxIterations is exceeded
adk.NewLoopAgent

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

Context Passing

SessionValues

A global KV store across Agents that can be read and written concurrently-safely 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 is based on Context implementation. The Runner reinitializes the Context at runtime. To inject data before a run, use the WithSessionValues Option:

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