Skip to content
Development
Skill

/eino-agent

Eino ADK agent construction, middleware, and runner. Use when a user needs to build an AI Agent, configure ChatModelAgent with ReAct pattern, use middleware (filesystem, tool search, tool reduction, summarization, plan-task, skill, agents.md), set up the Runner for event-driven

From plugin
eino-ext
7894 skills
Install
$ npx -y skills add cloudwego/eino-ext --skill eino-agent --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/eino-agent

Context preview

The summary Claude sees to decide when to auto-load this skill.

Eino ADK agent construction, middleware, and runner. Use when a user needs to build an AI Agent, configure ChatModelAgent with ReAct pattern, use middleware (filesystem, tool search, tool reduction, summarization, plan-task, skill, agents.md), set up the Runner for event-driven

SKILL.md

eino-agent.SKILL.md
name: eino-agent
description: Eino ADK agent construction, middleware, and runner. Use when a user needs to build an AI Agent, configure ChatModelAgent with ReAct pattern, use middleware (filesystem, tool search, tool reduction, summarization, plan-task, skill, agents.md), set up the Runner for event-driven execution, implement human-in-the-loop with interrupt/resume, use Cancel/Retry/Failover for model resilience, build push-based multi-turn loops with TurnLoop, or wrap agents as tools. Covers ChatModelAgent, DeepAgents, and TurnLoop.

Eino ADK Overview

Import: `github.com/cloudwego/eino/adk`

The Agent Development Kit (ADK) provides a framework for building agents in Go. The ADK is generically parameterized by `MessageType` to support both classic `*schema.Message` and the new `*schema.AgenticMessage`. Prefer `*schema.AgenticMessage` for new usage.

type MessageType interface {
    *schema.Message | *schema.AgenticMessage
}

type TypedAgent[M MessageType] interface {
    Name(ctx context.Context) string
    Description(ctx context.Context) string
    Run(ctx context.Context, input *TypedAgentInput[M], options ...AgentRunOption) *AsyncIterator[*TypedAgentEvent[M]]
}

// Convenience aliases for classic message type
type Agent = TypedAgent[*schema.Message]

Agent Types

| Type | Description | Decision | |------|-------------|----------| | ChatModelAgent | ReAct pattern: LLM reasons, calls tools, loops until done | Dynamic (LLM) | | DeepAgent | Pre-built agent with planning, filesystem, sub-agents | Dynamic (LLM) | | TurnLoop | Push-based event loop for multi-turn execution with preemption and lifecycle management | Runtime | | Custom Agent | Implement the TypedAgent interface directly | Custom |

ChatModelAgent Quick Start

import (
    "context"
    "fmt"
    "log"

    "github.com/cloudwego/eino-ext/components/model/openai"
    "github.com/cloudwego/eino/adk"
    "github.com/cloudwego/eino/components/tool"
    "github.com/cloudwego/eino/components/tool/utils"
    "github.com/cloudwego/eino/compose"
)

func main() {
    ctx := context.Background()

    // 1. Create a tool
    searchTool, _ := utils.InferTool("search_book", "Search books by genre",
        func(ctx context.Context, input *struct {
            Genre string `json:"genre" jsonschema_description:"Book genre"`
        }) (string, error) {
            return `{"books": ["The Great Gatsby"]}`, nil
        })

    // 2. Create model (BaseModel[M], not ToolCallingChatModel)
    cm, _ := openai.NewChatModel(ctx, &openai.ChatModelConfig{
        APIKey: "your-key", Model: "gpt-4o",
    })

    // 3. Create agent
    agent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
        Name:        "BookRecommender",
        Description: "Recommends books",
        Instruction: "You recommend books using the search_book tool.",
        Model:       cm,
        ToolsConfig: adk.ToolsConfig{
            ToolsNodeConfig: compose.ToolsNodeConfig{
                Tools: []tool.BaseTool{searchTool},
            },
        },
    })

    // 4. Run with Runner
    runner := adk.NewRunner(ctx, adk.RunnerConfig{Agent: agent})
    iter := runner.Query(ctx, "recommend a fiction book")
    for {
        event, ok := iter.Next()
        if !ok {
            break
        }
        if event.Err != nil {
            log.Fatal(event.Err)
        }
        if event.Output != nil && event.Output.MessageOutput != nil {
            msg, _ := event.Output.MessageOutput.GetMessage()
            fmt.Printf("Agent[%s]: %v\n", event.AgentName, msg)
        }
    }
}

Cancel Mechanism

Cancel provides safe, controllable termination of agent execution.

// Create a cancel function alongside the run
cancelOpt, cancelFn := adk.WithCancel()
iter := runner.Query(ctx, "do something", cancelOpt)

// ... iterate events ...

// Cancel at a safe point (cancelFn is non-blocking, Wait blocks until complete)
handle, ok := cancelFn(adk.WithAgentCancelMode(adk.CancelAfterChatModel))
if ok {
    handle.Wait()
}

**CancelMode** (bitmask):

| Mode | Behavior | |------|----------| | `CancelImmediate` (0) | Abort immediately, stream terminated | | `CancelAfterChatModel` | Wait for current model call to finish | | `CancelAfterToolCalls` | Wait for current tool calls to finish |

**Cancel options:**

  • `WithAgentCancelMode(mode)` -- set safe point
  • `WithAgentCancelTimeout(d)` -- escalate to immediate if safe point not reached in time
  • `WithRecursive()` -- propagate cancel into nested AgentTool agents

Cancel produces a `CancelError` on the event stream with checkpoint data for later resumption.

Model Retry

Output-based retry with full control over retry decisions.

agent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
    // ...
    ModelRetryConfig: &adk.ModelRetryConfig{
        MaxRetries: 3,
        ShouldRetry: func(ctx context.Context, retryCtx *adk.RetryContext) *adk.RetryDecision {
            // Retry based on output content (e.g., empty response, bad finish reason)
            if retryCtx.Err != nil {
                return &adk.RetryDecision{Retry: true, Backoff: time.Second}
            }
            if retryCtx.OutputMessage == nil || retryCtx.OutputMessage.Content == "" {
                return &adk.RetryDecision{Retry: true, Backoff: time.Second}
            }
            return &adk.RetryDecision{Retry: false}
        },
    },
})

**RetryContext** provides: `RetryAttempt`, `InputMessages`, `OutputMessage` (full concatenated response), `Err`.

**RetryDecision** controls: `Retry`, `ModifiedInputMessages`, `AdditionalOptions`, `Backoff`, `RejectReason`.

When streaming, a `WillRetryError` is emitted on the stream to signal retry is occurring.

Model Failover

Dynamic model switching when primary model fails or produces unsatisfactory output.

agent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
    // ...
    ModelFailoverConfig: &adk.ModelFailoverConfig[*schema.Message]
Read more
Ships witheino-ext

Various extensions for the Eino framework: https://github.com/cloudwego/eino

Get the whole plugin
Stats
790
Stars
348
Forks
Active
Maintenance
Go
Language
Apache-2.0
License
1d ago
Last commit
1y ago
Created

Repo: cloudwego/eino-ext