Skip to main content

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 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.

الانتقال إلى التثبيت

معلومات المصدر

المستودع
cloudwego/eino-ext
آخر نشاط في المصدر
٢٠ مايو ٢٠٢٦ في ٠٧:٥١
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٨١٣
التفرعات
٣٦٨

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
8 ملفات

عرض SKILL.md

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. ```go 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 ```go 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. ```go // 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. ```go 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. ```go agent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{ // ... ModelFailoverConfig: &adk.ModelFailoverConfig[*schema.Message]{ MaxRetries: 2, ShouldFailover: func(ctx context.Context, outputMessage *schema.Message, outputErr error) bool { return outputErr != nil // failover on any error }, GetFailoverModel: func(ctx context.Context, failoverCtx *adk.FailoverContext[*schema.Message]) ( model.BaseModel[*schema.Message], []*schema.Message, error) { // Return a different model and optionally modified input return backupModel, failoverCtx.InputMessages, nil }, }, }) ``` Failover interacts with Retry: when both are configured, `FailoverContext.LastErr` will be a `*RetryExhaustedError` if retry was also exhausted. # TurnLoop Push-based event loop for multi-turn agent execution with preemption, idle timeout, and graceful shutdown. ```go import "github.com/cloudwego/eino/adk" loop := adk.NewTurnLoop(adk.TurnLoopConfig[string, *schema.Message]{ GenInput: func(ctx context.Context, loop *adk.TurnLoop[string, *schema.Message], items []string) (*adk.GenInputResult[string, *schema.Message], error) { // Convert pushed items into agent input combined := strings.Join(items, "\n") return &adk.GenInputResult[string, *schema.Message]{ RunCtx: ctx, Input: &adk.TypedAgentInput[*schema.Message]{Messages: []*schema.Message{schema.UserMessage(combined)}}, Consumed: items, }, nil }, PrepareAgent: func(ctx context.Context, loop *adk.TurnLoop[string, *schema.Message], consumed []string) (adk.Agent, error) { return myAgent, nil }, OnAgentEvents: func(ctx context.Context, tc *adk.TurnContext[string, *schema.Message], events *adk.AsyncIterator[*adk.AgentEvent]) error { for { event, ok := events.Next() if !ok { break } if event.Err != nil { return event.Err } // Process events (e.g., send to client) } return nil }, }) // Start the loop loop.Run(ctx) // Push items (non-blocking, returns (ok bool, resolved <-chan struct{})) loop.Push("user message 1") // Preempt current turn with new input loop.Push("urgent message", adk.WithPreempt[string, *schema.Message](adk.AfterChatModel)) // Stop gracefully loop.Stop(adk.WithGraceful()) // Wait for exit and get final state exitState := loop.Wait() ``` **Key concepts:** - `Push()` queues items; the loop batches and processes them via `GenInput` - Preemption: cancel current turn at a safe point and start new turn with pending items - Idle timeout: `UntilIdleFor(d)` auto-stops after no items for duration `d` - Graceful shutdown: `WithGraceful()`, `WithGracefulTimeout(d)`, `WithImmediate()` - Exit state: `TurnLoopExitState` contains `ExitReason`, `UnhandledItems`, `InterruptedItems` # Runner The Runner manages agent lifecycle, context passing, and interrupt/resume: ```go runner := adk.NewRunner(ctx, adk.RunnerConfig{ Agent: myAgent, EnableStreaming: true, CheckPointStore: myStore, // for interrupt/resume }) // Query (convenience for single user message) iter := runner.Query(ctx, "hello") // Run (full control over input messages) iter := runner.Run(ctx, []*schema.Message{schema.UserMessage("hello")}) ``` # Middleware System Middleware extends ChatModelAgent behavior. Configure via `Handlers` field: ```go agent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{ // ... Handlers: []adk.ChatModelAgentMiddleware{fsMiddleware, summarizationMW}, }) ``` Eight built-in middleware types (see reference/middleware.md for details): | Middleware | Package | Purpose | |-----------|---------|---------| | FileSystem | `adk/middlewares/filesystem` | File ops (read/write/edit/glob/grep) + shell | | ToolSearch | `adk/middlewares/dynamictool/toolsearch` | Dynamic tool selection via regex search | | ToolReduction | `adk/middlewares/reduction` | Truncate/clear large tool results | | Summarization | `adk/middlewares/summarization` | Compress long conversation history | | PlanTask | `adk/middlewares/plantask` | Task creation and progress tracking | | Skill | `adk/middlewares/skill` | Skill-based progressive disclosure | | PatchToolCalls | `adk/middlewares/patchtoolcalls` | Fix dangling tool calls in history | | Agents.md | `adk/middlewares/agentsmd` | Inject Agents.md instructions into model input | # AgentAsTool Wrap any Agent as a Tool for use by another agent: ```go subAgent := createMySubAgent() agentTool := adk.NewAgentTool(ctx, subAgent) parentAgent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{ ToolsConfig: adk.ToolsConfig{ ToolsNodeConfig: compose.ToolsNodeConfig{ Tools: []tool.BaseTool{agentTool}, }, }, }) ``` # Human-in-the-Loop ChatModelAgent supports interrupt and resume for human approval, clarification, and feedback. See reference/human-in-the-loop.md for details. Key pattern: tool returns `compose.Interrupt(ctx, info)` to pause, then `runner.ResumeWithParams(ctx, checkpointID, params)` to continue. # Instructions to Agent - Default to `ChatModelAgent` for most use cases (single agent with tools) - Use `Runner` to execute agents -- never call `agent.Run()` directly in production - Middleware order matters: PatchToolCalls first, then Reduction, then Summarization - Use `DeepAgent` (`adk/prebuilt/deep`) when you need built-in planning + filesystem + sub-agents - Use `AgentAsTool` or DeepAgents' SubAgents when a sub-agent needs isolated context (no shared history) - Use `TurnLoop` when building interactive applications that need preemption, idle management, or push-based input - `Model` field accepts `model.BaseModel[M]` -- for classic path use any `BaseChatModel`, for agentic path use `AgenticModel` - Cancel, Retry, and Failover can all be combined; failover wraps retry - `WithCancel()` is a run option, not a config option -- create fresh per-run ## Reference Files Read these files on-demand for detailed API, examples, and advanced usage: - [reference/chat-model-agent.md](reference/chat-model-agent.md) -- ChatModelAgentConfig reference, ReAct pattern, ToolsConfig, streaming, Cancel/Retry/Failover details - [reference/deep-agents.md](reference/deep-agents.md) -- DeepAgent concept, config, architecture, comparison with ChatModelAgent - [reference/middleware.md](reference/middleware.md) -- All 8 middleware types with interface, config, and examples - [reference/runner-and-events.md](reference/runner-and-events.md) -- Runner creation, AgentEvent/AgentOutput, event iteration patterns - [reference/agent-as-tool.md](reference/agent-as-tool.md) -- Wrapping an Agent as a Tool for use by another agent - [reference/human-in-the-loop.md](reference/human-in-the-loop.md) -- Interrupt APIs, ResumableAgent, CheckPointStore, resume patterns - [reference/filesystem.md](reference/filesystem.md) -- Filesystem Backend interface, Local and AgentKit implementations, usage with DeepAgent
عرض على GitHub