diff --git a/content/en/docs/eino/Cookbook.md b/content/en/docs/eino/Cookbook.md
index 8b568409b4e..0485c508545 100644
--- a/content/en/docs/eino/Cookbook.md
+++ b/content/en/docs/eino/Cookbook.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-02"
+date: "2026-03-16"
lastmod: ""
tags: []
title: Cookbook
diff --git a/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_Ark_Agentkit_Sandbox.md b/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_Ark_Agentkit_Sandbox.md
index 3528a927361..6e9e702aa2e 100644
--- a/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_Ark_Agentkit_Sandbox.md
+++ b/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_Ark_Agentkit_Sandbox.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-02"
+date: "2026-03-16"
lastmod: ""
tags: []
title: 'Backend: Ark Agentkit Sandbox'
diff --git a/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_Local_FileSystem.md b/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_Local_FileSystem.md
index a81f29354c4..45d69c9eb1d 100644
--- a/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_Local_FileSystem.md
+++ b/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_Local_FileSystem.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-02"
+date: "2026-03-12"
lastmod: ""
tags: []
title: 'Backend: Local FileSystem'
@@ -11,7 +11,7 @@ weight: 2
Package: `github.com/cloudwego/eino-ext/adk/backend/local`
-Note: If your eino version is v0.8.0 or above, you need to use local backend [v0.2.0-alpha](https://github.com/cloudwego/eino-ext/releases/tag/adk%2Fbackend%2Flocal%2Fv0.2.0-alpha.1) version.
+Note: If your eino version is v0.8.0 or above, you need to use local backend [adk/backend/local/v0.2.1](https://github.com/cloudwego/eino-ext/releases/tag/adk%2Fbackend%2Flocal%2Fv0.2.1).
### Overview
diff --git a/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/_index.md b/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/_index.md
index 1c2b968a311..7b2441160d3 100644
--- a/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/_index.md
+++ b/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/_index.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-02"
+date: "2026-03-12"
lastmod: ""
tags: []
title: 'Middleware: FileSystem'
diff --git a/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_Skill.md b/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_Skill.md
index 5cf392861c8..c83bf6d7485 100644
--- a/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_Skill.md
+++ b/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_Skill.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-02"
+date: "2026-03-16"
lastmod: ""
tags: []
title: 'Middleware: Skill'
diff --git a/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_ToolReduction.md b/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_ToolReduction.md
index 6463d14c80a..7d6e8d9cb3d 100644
--- a/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_ToolReduction.md
+++ b/content/en/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_ToolReduction.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-02"
+date: "2026-03-12"
lastmod: ""
tags: []
title: 'Middleware: ToolReduction'
diff --git a/content/en/docs/eino/core_modules/eino_adk/adk_agent_callback.md b/content/en/docs/eino/core_modules/eino_adk/adk_agent_callback.md
index c75581d8489..9319dbf8634 100644
--- a/content/en/docs/eino/core_modules/eino_adk/adk_agent_callback.md
+++ b/content/en/docs/eino/core_modules/eino_adk/adk_agent_callback.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-02"
+date: "2026-03-12"
lastmod: ""
tags: []
title: 'Eino ADK: Agent Callback'
diff --git a/content/en/docs/eino/core_modules/eino_adk/agent_implementation/chat_model.md b/content/en/docs/eino/core_modules/eino_adk/agent_implementation/chat_model.md
index b7bfdf25a58..896acb5f25e 100644
--- a/content/en/docs/eino/core_modules/eino_adk/agent_implementation/chat_model.md
+++ b/content/en/docs/eino/core_modules/eino_adk/agent_implementation/chat_model.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-03"
+date: "2026-03-16"
lastmod: ""
tags: []
title: 'Eino ADK: ChatModelAgent'
diff --git a/content/en/docs/eino/core_modules/flow_integration_components/react_agent_manual.md b/content/en/docs/eino/core_modules/flow_integration_components/react_agent_manual.md
index e88e3e2ac46..b91b261e0ab 100644
--- a/content/en/docs/eino/core_modules/flow_integration_components/react_agent_manual.md
+++ b/content/en/docs/eino/core_modules/flow_integration_components/react_agent_manual.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-01-30"
+date: "2026-03-16"
lastmod: ""
tags: []
title: 'Eino: ReAct Agent Manual'
diff --git a/content/en/docs/eino/ecosystem_integration/_index.md b/content/en/docs/eino/ecosystem_integration/_index.md
index fd408ba5e13..7c831883a7e 100644
--- a/content/en/docs/eino/ecosystem_integration/_index.md
+++ b/content/en/docs/eino/ecosystem_integration/_index.md
@@ -11,9 +11,9 @@ weight: 6
### ChatModel
-- openai: [ChatModel - OpenAI](https://github.com/cloudwego/eino-ext/blob/main/components/model/openai/README.md)
-- ark: [ChatModel - ARK](https://github.com/cloudwego/eino-ext/blob/main/components/model/ark/README.md)
-- ollama: [ChatModel - Ollama](https://github.com/cloudwego/eino-ext/blob/main/components/model/ollama/README.md)
+- openai: [OpenAI](/docs/eino/ecosystem_integration/chat_model/agentic_model_openai)
+- ark: [ARK](/docs/eino/ecosystem_integration/chat_model/agentic_model_ark)
+- More components: [ChatModel component list](/docs/eino/ecosystem_integration/chat_model)
### Document
diff --git a/content/en/docs/eino/quick_start/_index.md b/content/en/docs/eino/quick_start/_index.md
index 505844a43b1..d50018aa4ff 100644
--- a/content/en/docs/eino/quick_start/_index.md
+++ b/content/en/docs/eino/quick_start/_index.md
@@ -1,40 +1,101 @@
---
Description: ""
-date: "2026-01-22"
+date: "2026-03-16"
lastmod: ""
tags: []
-title: 'Eino: Quick Start'
+title: 'Quick Start'
weight: 2
---
-## Overview
+This page is the unified entrypoint for the ChatWithEino Quickstart series: it provides a clear path to get you running and explains what you will build by the end (an extensible end-to-end Agent application skeleton).
-Eino offers component abstractions tailored for common AI application scenarios, with multiple implementations available. Getting a simple application up and running with Eino is **very straightforward**. This section presents a few of the most typical AI application examples to help you get productive quickly.
+## What is this
-These small examples are meant for quick onboarding. For deeper dives into specific capabilities and extended samples, see [Components](/docs/eino/core_modules/components) and [Orchestration](/docs/eino/core_modules/chain_and_graph_orchestration/chain_graph_introduction).
+ChatWithEino is a learning-oriented Agent built with Eino: it can read source code/docs/examples and help developers understand Eino and write Eino code through conversation.
-## Quick Start Examples
+This Quickstart series follows a “progressive build-up” approach:
-### Example: Minimal LLM Application
+- Start with a Console app, then progressively introduce ChatModel, Agent/Runner, Memory, Tools, Middleware, Callback, Interrupt/Resume, Graph Tool, and Skill
+- Deliver the same Agent as a Web app in the end, and use the A2UI protocol to render the event stream into an incrementally updating UI
-The most basic pattern in LLM applications is a `prompt + chat model`, which is also the primary capability offered by many AI platforms. You can define a `System Prompt` to constrain the model’s behavior (for example, “You are acting as role XXX”). In this example, you can combine Eino’s `PromptTemplate` and `ChatModel` components to build a role-playing application.
+## The shortest path: run it first
-- [Implement a minimal LLM application — ChatModel](/docs/eino/quick_start/simple_llm_application)
+In the repository root:
-### Example: Build an Agent
+```bash
+git clone https://github.com/cloudwego/eino-examples.git
+cd eino-examples/quickstart/chatwitheino
+```
-The LLM is the brain of an AI application: it understands natural language and produces responses. A text-only LLM accepts text and returns text. When you want the model to fetch information or perform actions, you introduce `Tools`. With tools, the model gains “hands” that can interact with existing IT infrastructure. For example, “call an HTTP API to check the weather, then suggest what to wear” requires the model to call a “search tool”.
+### 1) Minimal Console (Chapter 1)
-We call the overall system that decides when to call specific tools based on model outputs an “agent”.
+Prepare model config (OpenAI as an example):
-In Eino, you can implement an agent with `ChatModel + ToolsNode`, or use the built-in `react agent` and `multi agent` packages.
+```bash
+export OPENAI_API_KEY="..."
+export OPENAI_MODEL="gpt-4.1-mini"
+```
-In this example, we’ll use the ReAct agent to build an agent that interacts with the real world.
+Run:
-- [Agent — Give your LLM hands](/docs/eino/quick_start/agent_llm_with_tools)
+```bash
+go run ./cmd/ch01 -- "Explain in one sentence what problem Eino’s Component design solves."
+```
-## Next Steps
+### 2) Final Web (A2UI)
-- Understand Eino’s core modules and concepts: [Eino: Core Modules](/docs/eino/core_modules). This is the key knowledge to fluently develop applications with Eino.
-- Eino embraces an open ecosystem and provides numerous integration components: [Eino: Ecosystem Integration](/docs/eino/ecosystem_integration). Use these components to quickly assemble your business applications.
+```bash
+go run .
+```
+After it starts, open the address printed in the output (default `http://localhost:8080`).
+
+### 3) (Optional) Enable skills (Chapter 9 capability reuse)
+
+Skills inject a stable set of “knowledge/instruction packs” (`SKILL.md` + `reference/*.md`) into the Agent, so the model can load and call them on demand when needed.
+
+```bash
+go run ./scripts/sync_eino_ext_skills.go -src /path/to/eino-ext -dest ./skills/eino-ext -clean
+EINO_EXT_SKILLS_DIR="$(pwd)/skills/eino-ext" go run .
+```
+
+Notes:
+
+- The `./skills/` directory is ignored by `.gitignore` by default, to avoid accidentally committing synced skills
+- To verify Skills take effect, run the Chapter 9 entry code:
+ - [https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch09/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch09/main.go)
+
+## Learning path (chapter navigation)
+
+
+| Chapter | Topic | Entry |
+| Chapter 1 | ChatModel and Message (Console) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch01_chatmodel_agent_console.md |
+| Chapter 2 | Agent and Runner (Console multi-turn) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch02_chatmodel_agent_runner_console.md |
+| Chapter 3 | Memory and Session (persistent conversation) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch03_memory_session_jsonl.md |
+| Chapter 4 | Tools and file system access | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch04_tool_backend_filesystem.md |
+| Chapter 5 | Middleware pattern | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch05_middleware.md |
+| Chapter 6 | Callback and Trace (observability) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch06_callback.md |
+| Chapter 7 | Interrupt/Resume | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch07_interrupt_resume.md |
+| Chapter 8 | Graph Tool (complex workflows) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch08_graph_tool.md |
+| Chapter 9 | Skill (Console) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch09_skill.md |
+| Final | A2UI (Web) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch10_a2ui.md |
+
+
+## Final deliverable: an extensible end-to-end Agent application skeleton
+
+You can think of the final output of this Quickstart as a “pluggable application skeleton” that connects Eino’s key capabilities into a full loop:
+
+- Runtime: Runner drives execution, supporting streaming output and the event model
+- Tools: integrate file system/retrieval/workflows via Tool
+- Middleware: carry cross-cutting concerns like retries, approvals, and error handling via handler/middleware
+- Human-in-the-loop: interrupt/resume + checkpoint enable interactive flows like approval, missing-arg filling, and branch selection
+- Deterministic orchestration: compose (graph/chain/workflow) organizes complex business flows into maintainable, reusable execution graphs
+- UI delivery: map the Agent event stream to an incrementally renderable UI component tree with A2UI (SSE push)
+
+The boundary of A2UI is important: it is not part of the Eino framework itself; it is a business-layer UI protocol/rendering solution. This Quickstart uses it to demonstrate “how Agent capabilities can be delivered as a product”, and the details are defined by the final chapter.
+
+## Next explorations (from Quickstart to real business)
+
+- To systematically understand Eino’s component abstractions and usage: start from Chapter 1 and then fill in Tools/Graph/Callback/Interrupt step by step
+- To reuse larger-scale knowledge and instruction packs: integrate `eino-ext` skills and load them on demand via Skill middleware
+- To build an Agent into a business product: follow the final chapter (A2UI/Web) to connect event stream, state, and interaction, then replace it with your own UI form/protocol
diff --git a/content/en/docs/eino/quick_start/agent_llm_with_tools.md b/content/en/docs/eino/quick_start/agent_llm_with_tools.md
deleted file mode 100644
index e0e17f6981c..00000000000
--- a/content/en/docs/eino/quick_start/agent_llm_with_tools.md
+++ /dev/null
@@ -1,300 +0,0 @@
----
-Description: ""
-date: "2026-03-03"
-lastmod: ""
-tags: []
-title: Agent — Give Your LLM Hands
-weight: 2
----
-
-## What Is an Agent?
-
-An Agent is a system that perceives its environment and takes actions to achieve a goal. In AI applications, agents combine the language understanding of LLMs with tool execution, enabling them to autonomously complete complex tasks — a key form factor for how AI integrates into everyday work and life.
-
-> 💡
-> Example code snippets: [eino-examples/quickstart/todoagent](https://github.com/cloudwego/eino-examples/blob/master/quickstart/todoagent/main.go)
-
-## Core Components of an Agent
-
-In Eino, an agent typically consists of two core parts: a `ChatModel` and one or more `Tools`.
-
-### ChatModel
-
-`ChatModel` is the agent’s brain. It processes the user’s natural language input, understands intent, analyzes requirements, and decides whether a tool is needed. When tools are required, it selects the right tool with the right parameters and converts tool outputs back into natural-language responses.
-
-> More about ChatModel: [Eino: ChatModel Guide](/docs/eino/core_modules/components/chat_model_guide)
-
-### Tool
-
-`Tool` is the agent’s executor. Each tool has a clear function definition and parameter schema, allowing the `ChatModel` to call it accurately. Tools can wrap anything from simple data ops to sophisticated external service calls.
-
-> More about tools and ToolsNode: [Eino: ToolsNode Guide](/docs/eino/core_modules/components/tools_node_guide)
-
-## Implementing Tools
-
-Eino offers multiple ways to implement tools. We illustrate with a simple Todo management system.
-
-### Approach 1: Build with `NewTool`
-
-This is ideal for simpler tools: define tool metadata and a handler function.
-
-```go
-import (
- "context"
-
- "github.com/cloudwego/eino/components/tool"
- "github.com/cloudwego/eino/components/tool/utils"
- "github.com/cloudwego/eino/schema"
-)
-
-// Handler
-func AddTodoFunc(_ context.Context, params *TodoAddParams) (string, error) {
- // Mock
- return `{"msg": "add todo success"}`, nil
-}
-
-func getAddTodoTool() tool.InvokableTool {
- // Tool metadata
- info := &schema.ToolInfo{
- Name: "add_todo",
- Desc: "Add a todo item",
- ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
- "content": {
- Desc: "The content of the todo item",
- Type: schema.String,
- Required: true,
- },
- "started_at": {
- Desc: "The started time of the todo item, in unix timestamp",
- Type: schema.Integer,
- },
- "deadline": {
- Desc: "The deadline of the todo item, in unix timestamp",
- Type: schema.Integer,
- },
- }),
- }
-
- // Build with NewTool
- return utils.NewTool(info, AddTodoFunc)
-}
-```
-
-This approach is straightforward but has a drawback: parameter descriptions (`ParamsOneOf`) are separate from the actual parameter struct (`TodoAddParams`). Changes require updating both, risking inconsistency.
-
-### Approach 2: Build with `InferTool`
-
-This is more concise. Use struct tags to define parameter metadata so the description and struct share the same source.
-
-```go
-import (
- "context"
-
- "github.com/cloudwego/eino/components/tool/utils"
-)
-
-// Parameter struct
-type TodoUpdateParams struct {
- ID string `json:"id" jsonschema:"description=id of the todo"`
- Content *string `json:"content,omitempty" jsonschema:"description=content of the todo"`
- StartedAt *int64 `json:"started_at,omitempty" jsonschema:"description=start time in unix timestamp"`
- Deadline *int64 `json:"deadline,omitempty" jsonschema:"description=deadline of the todo in unix timestamp"`
- Done *bool `json:"done,omitempty" jsonschema:"description=done status"`
-}
-
-// Handler
-func UpdateTodoFunc(_ context.Context, params *TodoUpdateParams) (string, error) {
- // Mock
- return `{"msg": "update todo success"}`, nil
-}
-
-// Build tool with InferTool
-updateTool, err := utils.InferTool(
- "update_todo", // tool name
- "Update a todo item, eg: content,deadline...", // description
- UpdateTodoFunc)
-```
-
-### Approach 3: Implement the Tool Interface
-
-For advanced scenarios, implement the `Tool` interface.
-
-```go
-import (
- "context"
-
- "github.com/cloudwego/eino/components/tool"
- "github.com/cloudwego/eino/schema"
-)
-
-type ListTodoTool struct {}
-
-func (lt *ListTodoTool) Info(ctx context.Context) (*schema.ToolInfo, error) {
- return &schema.ToolInfo{
- Name: "list_todo",
- Desc: "List all todo items",
- ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
- "finished": {
- Desc: "filter todo items if finished",
- Type: schema.Boolean,
- Required: false,
- },
- }),
- }, nil
-}
-
-func (lt *ListTodoTool) InvokableRun(ctx context.Context, argumentsInJSON string, opts ...tool.Option) (string, error) {
- // Mock
- return `{"todos": [{"id": "1", "content": "Prepare Eino demo slides before 2024-12-10", "started_at": 1717401600, "deadline": 1717488000, "done": false}]}` , nil
-}
-```
-
-### Approach 4: Use Official Tools
-
-Beyond custom tools, Eino provides many well-tested, ready-to-use tools. For example, DuckDuckGo Search:
-
-```go
-import (
- "github.com/cloudwego/eino-ext/components/tool/duckduckgo"
-)
-
-
-// Create DuckDuckGo Search tool
-searchTool, err := duckduckgo.NewTool(ctx, &duckduckgo.Config{})
-```
-
-Using tools from `eino-ext` avoids reinvention and ensures reliability — they’re maintained and continuously improved.
-
-## Build an Agent with Chain
-
-`ToolsNode` is a core component for agents, managing tool invocation. It can host multiple tools and supports both synchronous (`Invoke`) and streaming (`Stream`) execution.
-
-To create a `ToolsNode`, provide a tool list configuration:
-
-```go
-import (
- "context"
-
- "github.com/cloudwego/eino/components/tool"
- "github.com/cloudwego/eino/compose"
-)
-
-conf := &compose.ToolsNodeConfig{
- Tools: []tool.BaseTool{tool1, tool2}, // tools can be InvokableTool or StreamableTool
-}
-toolsNode, err := compose.NewToolNode(context.Background(), conf)
-```
-
-Below is a complete agent example using OpenAI’s `ChatModel` and the Todo tools above:
-
-```go
-import (
- "context"
- "fmt"
- "log"
- "os"
-
- "github.com/cloudwego/eino-ext/components/model/openai"
- "github.com/cloudwego/eino/components/tool"
- "github.com/cloudwego/eino/compose"
- "github.com/cloudwego/eino/schema"
-)
-
-func main() {
- // Initialize tools
- todoTools := []tool.BaseTool{
- getAddTodoTool(), // NewTool
- updateTool, // InferTool
- &ListTodoTool{}, // Implement Tool interface
- searchTool, // Official tool
- }
-
- // Create and configure ChatModel
- chatModel, err := openai.NewChatModel(context.Background(), &openai.ChatModelConfig{
- Model: "gpt-4",
- APIKey: os.Getenv("OPENAI_API_KEY"),
- })
- if err != nil {
- log.Fatal(err)
- }
- // Bind tool infos to ChatModel
- toolInfos := make([]*schema.ToolInfo, 0, len(todoTools))
- for _, tool := range todoTools {
- info, err := tool.Info(ctx)
- if err != nil {
- log.Fatal(err)
- }
- toolInfos = append(toolInfos, info)
- }
- err = chatModel.BindTools(toolInfos)
- if err != nil {
- log.Fatal(err)
- }
-
-
- // Create tools node
- todoToolsNode, err := compose.NewToolNode(context.Background(), &compose.ToolsNodeConfig{
- Tools: todoTools,
- })
- if err != nil {
- log.Fatal(err)
- }
-
- // Build chain
- chain := compose.NewChain[[]*schema.Message, []*schema.Message]()
- chain.
- AppendChatModel(chatModel, compose.WithNodeName("chat_model")).
- AppendToolsNode(todoToolsNode, compose.WithNodeName("tools"))
-
- // Compile and run
- agent, err := chain.Compile(ctx)
- if err != nil {
- log.Fatal(err)
- }
-
- // Run example
- resp, err := agent.Invoke(ctx, []*schema.Message{
- {
- Role: schema.User,
- Content: "Add a TODO to learn Eino and search for the cloudwego/eino repo URL",
- },
- })
- if err != nil {
- log.Fatal(err)
- }
-
- // Print output
- for _, msg := range resp {
- fmt.Println(msg.Content)
- }
-}
-```
-
-This example assumes the `ChatModel` will decide to make tool calls when appropriate.
-
-## Other Ways to Build Agents
-
-Beyond Chain/Graph-based agents, Eino provides ready-made agent patterns.
-
-### ReAct Agent
-
-ReAct (Reasoning + Acting) combines deep reasoning with action through a think–act–observe loop. It’s well-suited for multi-step reasoning in complex tasks.
-
-> Learn more: [Eino: ReAct Agent Manual](/docs/eino/core_modules/flow_integration_components/react_agent_manual)
-
-### Multi Agent
-
-Multi-agent systems coordinate multiple agents, each with distinct responsibilities and expertise. Through interaction and collaboration, they can tackle complex tasks requiring multiple areas of knowledge.
-
-> Learn more: [Eino Tutorial: Host Multi-Agent](/docs/eino/core_modules/flow_integration_components/multi_agent_hosting)
-
-## Summary
-
-This article introduced core approaches to building agents with Eino. Using chains, tool calling, or ReAct patterns, you can flexibly construct AI agents to meet practical needs.
-
-Agents are a vital direction in AI — they understand user intent and take action by calling tools to accomplish complex tasks. As LLMs advance, agents will increasingly bridge AI and the real world. We hope Eino helps you build powerful, user-friendly agents and inspires new agent-driven applications.
-
-## Related Reading
-
-- Quick Start
- - [Build a Minimal LLM Application — ChatModel](/docs/eino/quick_start/simple_llm_application)
diff --git a/content/en/docs/eino/quick_start/chapter_01_chatmodel_and_message.md b/content/en/docs/eino/quick_start/chapter_01_chatmodel_and_message.md
new file mode 100644
index 00000000000..bc08710a458
--- /dev/null
+++ b/content/en/docs/eino/quick_start/chapter_01_chatmodel_and_message.md
@@ -0,0 +1,222 @@
+---
+Description: ""
+date: "2026-03-12"
+lastmod: ""
+tags: []
+title: "Chapter 1: ChatModel and Message (Console)"
+weight: 1
+---
+
+## Introduction to the Eino framework
+
+**What is Eino?**
+
+Eino is an AI application development framework in Go (Agent Development Kit) designed to help developers quickly build scalable and maintainable AI applications.
+
+**What problems does Eino solve?**
+
+1. **Model abstraction**: unify interfaces across different LLM providers (OpenAI, Ark, Claude, etc.), so switching models does not require changing business code
+2. **Capability composition**: provide replaceable, composable capability units through the Component interfaces (chat, tools, retrieval, etc.)
+3. **Orchestration framework**: offer orchestration abstractions such as Agent, Graph, and Chain to support complex multi-step AI workflows
+4. **Runtime support**: built-in streaming output, interrupt/resume, state management, and Callback-based observability
+
+**Main repositories of Eino:**
+
+- **eino** (this repo): the core library, defining interfaces, orchestration abstractions, and ADK
+- **eino-ext**: the extension library, providing concrete implementations of Components (OpenAI, Ark, Milvus, etc.)
+- **eino-examples**: the examples repo, including this Quickstart series
+
+---
+
+## ChatWithEino: an assistant that talks with Eino docs
+
+**What is ChatWithEino?**
+
+ChatWithEino is an intelligent assistant built with Eino. It helps developers learn Eino and write Eino code by accessing the Eino repository’s source code, comments, and examples, so it can provide accurate and up-to-date technical help.
+
+**Core capabilities:**
+
+- **Conversational interaction**: understand questions about Eino and respond clearly
+- **Code access**: read Eino source code/comments/examples and answer based on real implementations
+- **Persistent sessions**: support multi-turn conversations, remember context, and restore sessions across processes
+- **Tool calling**: perform operations such as file reading and code search
+
+**Architecture overview:**
+
+- **ChatModel**: communicate with LLM providers (OpenAI, Ark, Claude, etc.)
+- **Tool**: extend capabilities such as file system access and code search
+- **Memory**: persist conversation history
+- **Agent**: a unified execution framework that coordinates components
+
+## Quickstart series: build ChatWithEino from scratch
+
+This series walks you step by step: starting from the most basic ChatModel call, and progressively building a fully functional ChatWithEino Agent.
+
+**Learning path:**
+
+
+| Chapter | Topic | Core content | Capability gain |
+| Chapter 1 | ChatModel and Message | Understand the Component abstraction and implement a single-turn chat | Basic conversation |
+| Chapter 2 | Agent and Runner | Introduce execution abstractions and implement multi-turn chat | Session management |
+| Chapter 3 | Memory and Session | Persist chat history and support session recovery | Persistence |
+| Chapter 4 | Tools and file system | Add file access to read source code | Tool calling |
+| Chapter 5 | Middleware | Middleware mechanism and unified cross-cutting concerns | Extensibility |
+| Chapter 6 | Callback | Callbacks to observe the Agent execution process | Observability |
+| Chapter 7 | Interrupt and Resume | Interrupt and resume to support long-running tasks | Reliability |
+| Chapter 8 | Graph and Tool | Use Graph to orchestrate complex workflows | Complex orchestration |
+| Chapter 9 | A2UI | Integration from Agent to UI | Production-grade delivery |
+
+
+**Why design it this way?**
+
+Each chapter adds one core capability on top of the previous chapter, so you can:
+
+1. **Understand the role of each component**: features are introduced progressively instead of all at once
+2. **See the architecture evolve**: from simple to complex, and why each abstraction exists
+3. **Build practical skills**: every chapter comes with runnable code you can try hands-on
+
+---
+
+Goal of this chapter: understand Eino’s Component abstraction, call a ChatModel once with minimal code (with streaming output), and learn the basics of `schema.Message`.
+
+## Code location
+
+- Entry code: [cmd/ch01/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch01/main.go)
+
+## Why we need the Component interfaces
+
+Eino defines a set of Component interfaces (`ChatModel`, `Tool`, `Retriever`, `Loader`, etc.). Each interface describes one replaceable capability category:
+
+```go
+type BaseChatModel interface {
+ Generate(ctx context.Context, input []*schema.Message, opts ...Option) (*schema.Message, error)
+ Stream(ctx context.Context, input []*schema.Message, opts ...Option) (
+ *schema.StreamReader[*schema.Message], error)
+}
+```
+
+**Benefits of interfaces:**
+
+1. **Replaceable implementations**: `eino-ext` provides implementations for OpenAI, Ark, Claude, Ollama, and more. Business code depends only on the interface, so switching models only changes construction logic.
+2. **Composable orchestration**: orchestration layers such as Agent, Graph, and Chain depend only on Component interfaces, not concrete implementations. You can swap OpenAI for Ark without changing orchestration code.
+3. **Mockable in tests**: interfaces make mocking natural; unit tests do not need real model calls.
+
+This chapter focuses on `ChatModel`. Later chapters will introduce Components such as `Tool` and `Retriever`.
+
+## schema.Message: the basic unit of conversation
+
+`Message` is the basic structure for conversation data in Eino:
+
+```go
+type Message struct {
+ Role RoleType // system / user / assistant / tool
+ Content string // text content
+ ToolCalls []ToolCall // only assistant messages may have this
+ // ...
+}
+```
+
+Common constructors:
+
+```go
+schema.SystemMessage("You are a helpful assistant.")
+schema.UserMessage("What is the weather today?")
+schema.AssistantMessage("I don't know.", nil) // second arg is ToolCalls
+schema.ToolMessage("tool result", "call_id")
+```
+
+**Role semantics:**
+
+- `system`: system instructions, typically placed at the beginning of messages
+- `user`: user input
+- `assistant`: model response
+- `tool`: tool call result (covered in later chapters)
+
+## Prerequisites
+
+### Get the code
+
+```bash
+git clone https://github.com/cloudwego/eino-examples.git
+cd eino-examples/quickstart/chatwitheino
+```
+
+- Go version: Go 1.21+ (see `go.mod`)
+- A callable ChatModel (OpenAI by default; Ark is also supported)
+
+### Option A: OpenAI (default)
+
+```bash
+export OPENAI_API_KEY="..."
+export OPENAI_MODEL="gpt-4.1-mini" # OpenAI 2025 new model; gpt-4o / gpt-4o-mini also work
+# Optional:
+# OPENAI_BASE_URL (proxy or compatible service)
+# OPENAI_BY_AZURE=true (use Azure OpenAI)
+```
+
+### Option B: Ark
+
+```bash
+export MODEL_TYPE="ark"
+export ARK_API_KEY="..."
+export ARK_MODEL="..."
+# Optional: ARK_BASE_URL
+```
+
+## Run
+
+In `eino-examples/quickstart/chatwitheino`, run:
+
+```bash
+go run ./cmd/ch01 -- "Explain in one sentence what problem Eino’s Component design solves."
+```
+
+Example output (printed incrementally as the stream arrives):
+
+```
+[assistant] Eino’s Component design defines unified interfaces...
+```
+
+## What the entry code does
+
+In execution order:
+
+1. **Create a ChatModel**: choose OpenAI or Ark based on the `MODEL_TYPE` environment variable
+2. **Build input messages**: `SystemMessage(instruction)` + `UserMessage(query)`
+3. **Call Stream**: all ChatModel implementations must support `Stream()`, returning a `StreamReader[*Message]`
+4. **Print the result**: iterate `StreamReader` and print the assistant reply chunk by chunk
+
+Key code snippet (**note: simplified and not directly runnable; for the full code see** [cmd/ch01/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch01/main.go)):
+
+```go
+// Build input
+messages := []*schema.Message{
+ schema.SystemMessage(instruction),
+ schema.UserMessage(query),
+}
+
+// Call Stream (all ChatModels must implement this)
+stream, err := cm.Stream(ctx, messages)
+if err != nil {
+ log.Fatal(err)
+}
+defer stream.Close()
+
+for {
+ chunk, err := stream.Recv()
+ if errors.Is(err, io.EOF) {
+ break
+ }
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Print(chunk.Content)
+}
+```
+
+## Summary
+
+- **Component interfaces**: define boundaries for replaceable, composable, and testable capabilities
+- **Message**: the basic unit of conversation data, with semantics defined by roles
+- **ChatModel**: the most fundamental Component, providing `Generate` and `Stream`
+- **Implementation choice**: switch between OpenAI/Ark implementations via env/config without changing business code
diff --git a/content/en/docs/eino/quick_start/chapter_02_chatmodelagent_runner_agentevent.md b/content/en/docs/eino/quick_start/chapter_02_chatmodelagent_runner_agentevent.md
new file mode 100644
index 00000000000..ad2bd195ee6
--- /dev/null
+++ b/content/en/docs/eino/quick_start/chapter_02_chatmodelagent_runner_agentevent.md
@@ -0,0 +1,26 @@
+---
+Description: ""
+date: "2026-03-12"
+lastmod: ""
+tags: []
+title: "Chapter 2: ChatModelAgent, Runner, AgentEvent (Console multi-turn)"
+weight: 2
+---
+
+Goal of this chapter: introduce ADK execution abstractions (Agent + Runner) and implement a multi-turn conversation in a Console program.
+
+## Code location
+
+- Entry code: [cmd/ch02/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch02/main.go)
+
+## Full tutorial
+
+This page is a website-friendly overview. For the full runnable walkthrough, see:
+
+- [ch02_chatmodel_agent_runner_console.md](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch02_chatmodel_agent_runner_console.md)
+
+## What you learn
+
+- Why “Agent” is a higher-level abstraction than “ChatModel”: it owns the interaction loop and tool routing.
+- What “Runner” does: it provides the runtime (streaming, events, interrupt/resume plumbing) for running an Agent.
+- How “AgentEvent” models the execution stream: user input, model output, tool calls, tool results, and lifecycle signals.
diff --git a/content/en/docs/eino/quick_start/chapter_03_memory_and_session.md b/content/en/docs/eino/quick_start/chapter_03_memory_and_session.md
new file mode 100644
index 00000000000..e90a0a8e990
--- /dev/null
+++ b/content/en/docs/eino/quick_start/chapter_03_memory_and_session.md
@@ -0,0 +1,28 @@
+---
+Description: ""
+date: "2026-03-12"
+lastmod: ""
+tags: []
+title: "Chapter 3: Memory and Session (persistent conversations)"
+weight: 3
+---
+
+Goal of this chapter: persist conversation history and support session recovery across processes.
+
+> ⚠️ Important note: **Memory, Session, and Store here are business-layer concepts**, not core Eino framework components.
+>
+> Eino focuses on “how to process messages”; “how to store messages” is entirely up to your application (DB/Redis/object storage/etc.). The implementation in this chapter is a simple reference you can replace.
+
+## Code location
+
+- Entry code: [cmd/ch03/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch03/main.go)
+
+## Full tutorial
+
+- [ch03_memory_session_jsonl.md](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch03_memory_session_jsonl.md)
+
+## What you learn
+
+- How to model “Session” as a stable ID and resume a conversation by reloading stored messages.
+- A simple storage format (JSONL) as a baseline for implementing your own persistence layer.
+- How to integrate persistence with the Agent/Runner loop without coupling it into Eino itself.
diff --git a/content/en/docs/eino/quick_start/chapter_04_tool_and_filesystem.md b/content/en/docs/eino/quick_start/chapter_04_tool_and_filesystem.md
new file mode 100644
index 00000000000..aff152a9b87
--- /dev/null
+++ b/content/en/docs/eino/quick_start/chapter_04_tool_and_filesystem.md
@@ -0,0 +1,33 @@
+---
+Description: ""
+date: "2026-03-12"
+lastmod: ""
+tags: []
+title: "Chapter 4: Tools and file system access"
+weight: 4
+---
+
+Goal of this chapter: add Tool capabilities so the Agent can access the file system.
+
+## Why Tools
+
+In Chapters 1–3, the Agent can only chat; it cannot perform real actions.
+
+Typical limitations without tools:
+
+- Only generates text responses
+- Cannot access external resources (files/APIs/databases)
+- Cannot execute real tasks (compute/query/modify)
+
+## Code location
+
+- Entry code: [cmd/ch04/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch04/main.go)
+
+## Full tutorial
+
+- [ch04_tool_backend_filesystem.md](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch04_tool_backend_filesystem.md)
+
+## What you learn
+
+- How to expose file reads as tools and let the model call them through the Agent.
+- How to keep tool boundaries explicit (inputs/outputs) so they are testable and observable.
diff --git a/content/en/docs/eino/quick_start/chapter_05_middleware.md b/content/en/docs/eino/quick_start/chapter_05_middleware.md
new file mode 100644
index 00000000000..d15b7f96640
--- /dev/null
+++ b/content/en/docs/eino/quick_start/chapter_05_middleware.md
@@ -0,0 +1,33 @@
+---
+Description: ""
+date: "2026-03-16"
+lastmod: ""
+tags: []
+title: "Chapter 5: Middleware (cross-cutting concerns)"
+weight: 5
+---
+
+Goal of this chapter: understand the middleware pattern and implement Tool error handling and ChatModel retry.
+
+## Why Middleware
+
+Once you add tools (Chapter 4), failures become normal in real-world systems:
+
+- Tool failures: file not found, invalid args, missing permissions, etc.
+- ChatModel failures: rate limits (429), network timeouts, temporary outages, etc.
+
+Middleware provides a single place to handle these cross-cutting concerns without scattering logic throughout your business code.
+
+## Code location
+
+- Entry code: [cmd/ch05/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch05/main.go)
+
+## Full tutorial
+
+- [ch05_middleware.md](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch05_middleware.md)
+
+## What you learn
+
+- How to wrap tool execution with consistent error handling.
+- How to add retry policies around ChatModel calls in a composable way.
+- How middleware keeps the Agent core clean and extensible.
diff --git a/content/en/docs/eino/quick_start/chapter_06_callback_and_trace.md b/content/en/docs/eino/quick_start/chapter_06_callback_and_trace.md
new file mode 100644
index 00000000000..397af7dae31
--- /dev/null
+++ b/content/en/docs/eino/quick_start/chapter_06_callback_and_trace.md
@@ -0,0 +1,23 @@
+---
+Description: ""
+date: "2026-03-12"
+lastmod: ""
+tags: []
+title: "Chapter 6: Callback and Trace (observability)"
+weight: 6
+---
+
+Goal of this chapter: understand the Callback mechanism and integrate tracing/observability for the Agent execution.
+
+## Code location
+
+- Entry code: [cmd/ch06/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch06/main.go)
+
+## Full tutorial
+
+- [ch06_callback.md](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch06_callback.md)
+
+## What you learn
+
+- How callbacks expose lifecycle hooks for key execution points (model calls, tool calls, streaming chunks).
+- How to build logging/metrics/tracing without coupling instrumentation into core logic.
diff --git a/content/en/docs/eino/quick_start/chapter_07_interrupt_resume.md b/content/en/docs/eino/quick_start/chapter_07_interrupt_resume.md
new file mode 100644
index 00000000000..fe5fdfa2924
--- /dev/null
+++ b/content/en/docs/eino/quick_start/chapter_07_interrupt_resume.md
@@ -0,0 +1,23 @@
+---
+Description: ""
+date: "2026-03-16"
+lastmod: ""
+tags: []
+title: "Chapter 7: Interrupt/Resume (human-in-the-loop)"
+weight: 7
+---
+
+Goal of this chapter: understand Interrupt/Resume and implement an approval flow so users can confirm before sensitive tool operations.
+
+## Code location
+
+- Entry code: [cmd/ch07/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch07/main.go)
+
+## Full tutorial
+
+- [ch07_interrupt_resume.md](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch07_interrupt_resume.md)
+
+## What you learn
+
+- How to pause an execution at a safe boundary and request user input.
+- How to resume from checkpoints to support long-running or approval-gated tasks.
diff --git a/content/en/docs/eino/quick_start/chapter_08_graph_tool.md b/content/en/docs/eino/quick_start/chapter_08_graph_tool.md
new file mode 100644
index 00000000000..e842eadb624
--- /dev/null
+++ b/content/en/docs/eino/quick_start/chapter_08_graph_tool.md
@@ -0,0 +1,24 @@
+---
+Description: ""
+date: "2026-03-12"
+lastmod: ""
+tags: []
+title: "Chapter 8: Graph Tool (complex workflows)"
+weight: 8
+---
+
+Goal of this chapter: understand the Graph Tool concept and build more complex workflows using the compose package.
+
+## Code location
+
+- Entry code: [cmd/ch08/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch08/main.go)
+- RAG implementation: [rag/rag.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/rag/rag.go)
+
+## Full tutorial
+
+- [ch08_graph_tool.md](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch08_graph_tool.md)
+
+## What you learn
+
+- How to decompose a complex task into a deterministic execution graph.
+- How to parallelize “chunking + retrieval” for large files and aggregate results back into a final answer.
diff --git a/content/en/docs/eino/quick_start/chapter_09_a2ui_protocol.md b/content/en/docs/eino/quick_start/chapter_09_a2ui_protocol.md
new file mode 100644
index 00000000000..3f1c4246564
--- /dev/null
+++ b/content/en/docs/eino/quick_start/chapter_09_a2ui_protocol.md
@@ -0,0 +1,24 @@
+---
+Description: ""
+date: "2026-03-16"
+lastmod: ""
+tags: []
+title: "Final: A2UI protocol (streaming UI components)"
+weight: 10
+---
+
+Goal of this chapter: implement the A2UI protocol and render the Agent output as a stream of UI components.
+
+## Important: A2UI’s boundary
+
+A2UI is not part of the Eino framework itself. It is a business-layer UI protocol/rendering approach. This chapter integrates A2UI into the Agent you built across previous chapters to provide an end-to-end, production-oriented example: model calls, tool calls, workflow orchestration, and finally delivering results as a more user-friendly UI.
+
+In real-world products, you can choose different UI forms depending on your product:
+
+- Web/App: custom components, tables, cards, charts
+- IM/office suite: message cards, interactive forms
+- CLI: plain text or TUI
+
+## Full tutorial
+
+- [ch10_a2ui.md](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch10_a2ui.md)
diff --git a/content/en/docs/eino/quick_start/chapter_09_skill_console.md b/content/en/docs/eino/quick_start/chapter_09_skill_console.md
new file mode 100644
index 00000000000..6f7558bcbfd
--- /dev/null
+++ b/content/en/docs/eino/quick_start/chapter_09_skill_console.md
@@ -0,0 +1,24 @@
+---
+Description: ""
+date: "2026-03-16"
+lastmod: ""
+tags: []
+title: "Chapter 9: Skill (Console)"
+weight: 9
+---
+
+Goal of this chapter: introduce the `skill` middleware so the Agent can discover and load reusable skill documents (`SKILL.md`) and use them on demand through tool calls.
+
+## Code location
+
+- Entry code: [cmd/ch09/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch09/main.go)
+- Sync script: [scripts/sync_eino_ext_skills.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/scripts/sync_eino_ext_skills.go)
+
+## Full tutorial
+
+- [ch09_skill.md](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch09_skill.md)
+
+## What you learn
+
+- How “progressive disclosure” works for skills (index → load on demand).
+- How to integrate skills into an Agent without permanently inflating prompt context.
diff --git a/content/en/docs/eino/quick_start/simple_llm_application.md b/content/en/docs/eino/quick_start/simple_llm_application.md
deleted file mode 100644
index 219c8c1a97c..00000000000
--- a/content/en/docs/eino/quick_start/simple_llm_application.md
+++ /dev/null
@@ -1,207 +0,0 @@
----
-Description: ""
-date: "2026-01-20"
-lastmod: ""
-tags: []
-title: Building a Simple LLM Application
-weight: 1
----
-
-This guide will help you quickly get started using Eino framework's ChatModel to build a simple LLM application. We will demonstrate how to use ChatModel through implementing a "Programmer Encouragement Assistant" example.
-
-> 💡
-> Code snippets from the examples in this article can be found at: [eino-examples/quickstart/chat](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chat)
-
-## **ChatModel Introduction**
-
-ChatModel is Eino framework's abstraction for conversational large models, providing a unified interface to interact with different large model services (such as OpenAI, Ollama, etc.).
-
-> For more detailed component introduction, see: [Eino: ChatModel Guide](/docs/eino/core_modules/components/chat_model_guide)
-
-## **Message Structure and Usage**
-
-In Eino, conversations are represented through `schema.Message`, which is Eino's abstract definition of a conversation message. Each Message contains the following important fields:
-
-- `Role`: The role of the message, which can be:
- - `system`: System instruction, used to set the model's behavior and role
- - `user`: User input
- - `assistant`: Model's reply
- - `tool`: Tool call result
-- `Content`: The specific content of the message
-
-## **Implementing the Programmer Encouragement Assistant**
-
-Let's learn how to use ChatModel by implementing a Programmer Encouragement Assistant. This assistant can not only provide technical advice but also offer psychological support when programmers feel discouraged.
-
-### Creating Conversation Templates and Generating Messages
-
-Eino provides powerful templating functionality for building messages to input to the large model:
-
-1. Template rendering, supporting three template formats:
-
- - FString: Python-style simple string formatting (e.g., "Hello, {name}!")
- - Jinja2: Jinja2-style templates supporting rich expressions (e.g., "Hello, {{name}}!")
- - GoTemplate: Go's built-in text/template format (e.g., "Hello, {{.name}}!")
-2. Message placeholders: Support inserting a group of messages (such as conversation history)
-
-```go
-// optional=false means required message list, will error if corresponding variable not found in template input
-schema.MessagesPlaceholder("chat_history", false)
-```
-
-> For more detailed component introduction, see: [Eino: ChatTemplate Guide](/docs/eino/core_modules/components/chat_template_guide)
-
-Below is the complete code for creating and using conversation templates with FString format + message placeholders:
-
-```go
-// eino-examples/quickstart/chat/template.go
-
-import (
- "context"
-
- "github.com/cloudwego/eino/components/prompt"
- "github.com/cloudwego/eino/schema"
-)
-
-// Create template using FString format
-template := prompt.FromMessages(schema.FString,
- // System message template
- schema.SystemMessage("You are a {role}. You need to respond in a {style} tone. Your goal is to help programmers maintain a positive and optimistic mindset, providing technical advice while also caring about their mental health."),
-
- // Insert needed conversation history (leave empty for new conversations)
- schema.MessagesPlaceholder("chat_history", true),
-
- // User message template
- schema.UserMessage("Question: {question}"),
-)
-
-// Use template to generate messages
-messages, err := template.Format(context.Background(), map[string]any{
- "role": "Programmer Encouragement Assistant",
- "style": "positive, warm, and professional",
- "question": "My code keeps throwing errors, I feel so frustrated, what should I do?",
- // Conversation history (simulating two rounds of conversation history in this example)
- "chat_history": []*schema.Message{
- schema.UserMessage("Hello"),
- schema.AssistantMessage("Hey! I'm your Programmer Encouragement Assistant! Remember, every excellent programmer grows through debugging. How can I help you?", nil),
- schema.UserMessage("I feel like the code I write is terrible"),
- schema.AssistantMessage("Every programmer goes through this stage! What's important is that you're constantly learning and improving. Let's look at the code together, I believe through refactoring and optimization, it will get better. Remember, Rome wasn't built in a day, code quality improves through continuous improvement.", nil),
- },
-})
-```
-
-### Creating a ChatModel
-
-ChatModel is one of the most core components in the Eino framework, providing a unified interface for interacting with various large language models. Eino currently supports the following large language model implementations:
-
-- OpenAI: Supports GPT-3.5/GPT-4 and other models (also supports Azure-provided OpenAI services)
-- Ollama: Supports locally deployed open-source models
-- Ark: Model services on Volcano Engine (e.g., ByteDance's Doubao model)
-- More models are being added
-
-> For supported models, see: [Eino: Ecosystem Integration](/docs/eino/ecosystem_integration)
-
-Below we demonstrate how to create and use ChatModel using OpenAI and Ollama as examples:
-
-#### **OpenAI (choose either this or Ollama below)**
-
-```go
-// eino-examples/quickstart/chat/openai.go
-
-import (
- "os"
-
- "github.com/cloudwego/eino-ext/components/model/openai"
-)
-
-chatModel, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
- Model: "gpt-4o", // Model version to use
- APIKey: os.Getenv("OPENAI_API_KEY"), // OpenAI API key
-})
-```
-
-> For detailed information about OpenAI ChatModel, see: [ChatModel - OpenAI](https://github.com/cloudwego/eino-ext/blob/main/components/model/openai/README.md)
-
-#### **Ollama (choose either this or OpenAI above)**
-
-Ollama supports running open-source models locally, suitable for scenarios with data privacy requirements or offline usage needs.
-
-```go
-// eino-examples/quickstart/chat/ollama.go
-
-import (
- "github.com/cloudwego/eino-ext/components/model/ollama"
-)
-
-
-chatModel, err := ollama.NewChatModel(ctx, &ollama.ChatModelConfig{
- BaseURL: "http://localhost:11434", // Ollama service address
- Model: "llama2", // Model name
-})
-```
-
-> For detailed information about Ollama ChatModel, see: [ChatModel - Ollama](https://github.com/cloudwego/eino-ext/blob/main/components/model/ollama/README.md)
-
-Eino provides a unified ChatModel abstraction for large models and offers ready-to-use implementations of various LLMs. Therefore, business code can focus on writing business logic without worrying about model implementation details. When model implementations are updated, they won't affect core business logic, meaning developers can easily switch between different models without modifying large amounts of code.
-
-### Running the ChatModel
-
-After obtaining the ChatModel input messages and the initialized ChatModel instance through the previous two steps, you can start trying to run the ChatModel. Eino ChatModel provides two running modes: output complete message (generate) and output message stream (stream):
-
-```go
-// eino-examples/quickstart/chat/generate.go
-
-/*** create messages
-* messages, err := xxx
-*/
-
-/*** create chat model
-* chatModel, err := xxx
-*/
-
-result, err := chatModel.Generate(ctx, messages)
-streamResult, err := chatModel.Stream(ctx, messages)
-```
-
-In practical applications, there are many scenarios that need streaming responses. The main scenario is "improving user experience": the stream running mode allows ChatModel to provide typewriter-like output, giving users model responses earlier.
-
-Here's how Eino handles streaming output:
-
-```go
-// eino-examples/quickstart/chat/stream.go
-
-import (
- "io"
- "log"
-
- "github.com/cloudwego/eino/schema"
-)
-
-func reportStream(sr *schema.StreamReader[*schema.Message]) {
- defer sr.Close()
-
- i := 0
- for {
- message, err := sr.Recv()
- if err == io.EOF { // Streaming output ended
- return
- }
- if err != nil {
- log.Fatalf("recv failed: %v", err)
- }
- log.Printf("message[%d]: %+v\n", i, message)
- i++
- }
-}
-```
-
-For the complete implementation, see: [eino-examples/quickstart/chat/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chat/main.go)
-
-## **Summary**
-
-This example demonstrated how to build an LLM application using the Eino framework through a Programmer Encouragement Assistant case. From creating a ChatModel to using message templates to actual conversation implementation, you should now have a basic understanding of the Eino framework. Whether you choose OpenAI, Ollama, or other model implementations, Eino provides a unified and simple way to use them. We hope this example helps you quickly start building your own LLM applications.
-
-## **Related Reading**
-
-- Quick Start
- - [Agent - Give LLMs Hands](/docs/eino/quick_start/agent_llm_with_tools)
diff --git a/content/zh/docs/eino/Cookbook.md b/content/zh/docs/eino/Cookbook.md
index d8268d94759..db3b6c8f616 100644
--- a/content/zh/docs/eino/Cookbook.md
+++ b/content/zh/docs/eino/Cookbook.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-02"
+date: "2026-03-16"
lastmod: ""
tags: []
title: Cookbook
diff --git a/content/zh/docs/eino/FAQ.md b/content/zh/docs/eino/FAQ.md
index d062f4d4b96..5f4b47f5f00 100644
--- a/content/zh/docs/eino/FAQ.md
+++ b/content/zh/docs/eino/FAQ.md
@@ -142,7 +142,7 @@ eino-ext 支持的多模态输入输出场景,可以查阅 [https://www.cloudw
eino-ext 部分 module 报错 undefined: schema.NewParamsOneOfByOpenAPIV3 等问题,升级报错的 eino-ext module 到最新版本即可。
-如果 schema 改造比较复杂,可以使用现有的 OpenAPI 3.0 → JSONSchema 转换工具方法辅助转换。
+如果 schema 改造比较复杂,可以参考上面的 Discussion #397,使用其中的 JSONSchema 转换工具方法辅助转换。
# Q: Eino-ext 提供的 ChatModel 有哪些模型是支持 Response API 形式调用嘛?
diff --git a/content/zh/docs/eino/core_modules/chain_and_graph_orchestration/stream_programming_essentials.md b/content/zh/docs/eino/core_modules/chain_and_graph_orchestration/stream_programming_essentials.md
index 39ef62359a2..9c7025c0804 100644
--- a/content/zh/docs/eino/core_modules/chain_and_graph_orchestration/stream_programming_essentials.md
+++ b/content/zh/docs/eino/core_modules/chain_and_graph_orchestration/stream_programming_essentials.md
@@ -101,7 +101,7 @@ Collect 和 Transform 两种流式范式,目前只在编排场景有用到。
上面的 Concat message stream 是 Eino 框架自动提供的能力,即使不是 message,是任意的 T,只要满足特定的条件,Eino 框架都会自动去做这个 StreamReader[T] 到 T 的转化,这个条件是:**在编排中,当一个组件的上游输出是 StreamReader[T],但是组件只提供了 T 作为输入的业务接口时,框架会自动将 StreamReader[T] concat 成 T,再输入给这个组件。**
> 💡
-> 框架自动将 StreamReader[T] concat 成 T 的过程,可能需要用户提供一个 Concat function。详见 [Eino: 编排的设计理念](/zh/docs/eino/core_modules/chain_and_graph_orchestration/orchestration_design_principles) 中关于“合并帧”的章节。
+> 框架自动将 StreamReader[T] concat 成 T 的过程,可能需要用户提供一个 Concat function。详见 [Eino: 编排的设计理念](/zh/docs/eino/core_modules/chain_and_graph_orchestration/orchestration_design_principles#share-FaVnd9E2foy4fAxtbTqcsgq3n5f) 中关于“合并帧”的章节。
另一方面,考虑一个相反的例子。还是 React Agent,这次是一个更完整的编排示意图:
diff --git a/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_Ark_Agentkit_Sandbox.md b/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_Ark_Agentkit_Sandbox.md
index b80be13db1c..68e9eac2d4c 100644
--- a/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_Ark_Agentkit_Sandbox.md
+++ b/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_Ark_Agentkit_Sandbox.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-10"
+date: "2026-03-16"
lastmod: ""
tags: []
title: Ark Agentkit Sandbox
diff --git "a/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_\346\234\254\345\234\260\346\226\207\344\273\266\347\263\273\347\273\237.md" "b/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_\346\234\254\345\234\260\346\226\207\344\273\266\347\263\273\347\273\237.md"
index 356d445ddd8..4f1b07ab907 100644
--- "a/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_\346\234\254\345\234\260\346\226\207\344\273\266\347\263\273\347\273\237.md"
+++ "b/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/Backend_\346\234\254\345\234\260\346\226\207\344\273\266\347\263\273\347\273\237.md"
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-10"
+date: "2026-03-12"
lastmod: ""
tags: []
title: 本地文件系统
@@ -218,6 +218,10 @@ absPath, _ := filepath.Abs("./relative/path")
### 常见问题
+**Q: 为什么运行 grep 命令报错 ripgrep (rg) is not installed or not in PATH. Please install it: ****[https://github.com/BurntSushi/ripgrep#installation](https://github.com/BurntSushi/ripgrep#installation)**
+
+local 的 Grep 命令默认依赖** ripgrep **指令,如系统没有预装 ripgrep 则需要通过文档安装 ripgrep
+
**Q: GrepRaw 支持正则吗?**
支持正则匹配,GrepRaw 底层使用的是 ripgrep 命令做的 Grep 操作
diff --git a/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/_index.md b/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/_index.md
index e108aabe972..498bbcfd721 100644
--- a/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/_index.md
+++ b/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_FileSystem/_index.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-02"
+date: "2026-03-12"
lastmod: ""
tags: []
title: FileSystem
diff --git a/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_Skill.md b/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_Skill.md
index beaa5fa0857..5e7acbdaa83 100644
--- a/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_Skill.md
+++ b/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_Skill.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-10"
+date: "2026-03-16"
lastmod: ""
tags: []
title: Skill
@@ -50,7 +50,7 @@ type FrontMatter struct {
| 字段 | 类型 | 说明 |
Name | string | Skill 的唯一标识符。Agent 通过此名称调用 Skill ,建议使用简短、有意义的名称(如 pdf-processing 、web-research )。对应 SKILL.md 中 frontmatter 的 name 字段 |
Description | string | Skill 的功能描述。这是 Agent 判断是否使用该 Skill 的关键依据,应清晰说明技 Skill 能适用的场景和能力。对应 SKILL.md 中 frontmatter 的 description 字段 |
-Context | ContextMode | 上下文模式。可选值:fork (复制历史消息创建新 Agent 执行)、isolate (隔离上下文创建新 Agent 执行)。留空表示内联模式(直接返回 Skill 内容) |
+Context | ContextMode | 上下文模式。可选值:fork_with_context (复制历史消息创建新 Agent 执行)、fork (隔离上下文创建新 Agent 执行)。留空表示内联模式(直接返回 Skill 内容) |
Agent | string | 指定使用的 Agent 名称。配合 Context 字段使用,通过 AgentHub 获取对应的 Agent 工厂函数。留空时使用默认 Agent |
Model | string | 指定使用的模型名称。通过 ModelHub 获取对应的模型实例。在 Context 模式下传递给 Agent 工厂;在内联模式下切换后续 ChatModel 调用使用的模型 |
@@ -59,16 +59,16 @@ type FrontMatter struct {
```go
const (
- ContextModeFork ContextMode = "fork" // 复制历史消息
- ContextModeIsolate ContextMode = "isolate" // 隔离上下文
+ ContextModeFork ContextMode = "fork" // 复制历史消息
+ ContextModeForkWithContext ContextMode = "fork_with_context" // 隔离上下文
)
```
| 模式 | 说明 |
| 内联(默认) | Skill 内容直接作为工具结果返回,由当前 Agent 继续处理 |
-| Fork | 创建新 Agent,复制当前对话历史,独立执行 Skill 任务后返回结果 |
-| Isolate | 创建新 Agent,使用隔离的上下文(仅包含 Skill 内容),独立执行后返回结果 |
+| ForkWithContext | 创建新 Agent,复制当前对话历史,独立执行 Skill 任务后返回结果 |
+| Fork | 创建新 Agent,使用隔离的上下文(仅包含 Skill 内容),独立执行后返回结果 |
## Skill
@@ -283,7 +283,7 @@ type Config struct {
# 快速开始
-以从本地加载 pdf skill 为例, 完整代码见 [https://github.com/cloudwego/eino-examples/tree/alpha/08/adk/middlewares/skill](https://github.com/cloudwego/eino-examples/tree/alpha/08/adk/middlewares/skill)。
+以从本地加载 pdf skill 为例, 完整代码见 [https://github.com/cloudwego/eino-examples/tree/main/adk/middlewares/skill](https://github.com/cloudwego/eino-examples/tree/main/adk/middlewares/skill)。
- 在工作目录中创建 skills 目录:
@@ -305,20 +305,24 @@ import (
"github.com/cloudwego/eino-ext/adk/backend/local"
)
+ctx := context.Background()
be, err := local.NewBackend(ctx, &local.Config{})
if err != nil {
log.Fatal(err)
}
-wd, _ := os.Getwd()
-workDir := filepath.Join(wd, "adk", "middlewares", "skill", "workdir")
skillBackend, err := skill.NewBackendFromFilesystem(ctx, &skill.BackendFromFilesystemConfig{
Backend: be,
BaseDir: skillsDir,
})
+if err != nil {
+ log.Fatalf("Failed to create skill backend: %v", err)
+}
-skillMiddleware, err := NewMiddleware(ctx, &Config{Backend: backend})
+sm, err := skill.NewMiddleware(ctx, &skill.Config{
+ Backend: skillBackend,
+})
```
- 基于 backend 创建本地 Filesystem Middleware,供 agent 读取 skill 其他文件以及执行脚本:
@@ -329,8 +333,8 @@ import (
)
fsm, err := filesystem.New(ctx, &filesystem.MiddlewareConfig{
- Backend: be,
- WithoutLargeToolResultOffloading: true,
+ Backend: be,
+ StreamingShell: be,
})
```
@@ -342,7 +346,7 @@ agent, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Description: "An agent that can analyze logs",
Instruction: "You are a helpful assistant.",
Model: cm,
- Handlers: []adk.ChatModelAgentMiddleware{fsm, skillMiddleware},
+ Handlers: []adk.ChatModelAgentMiddleware{fsm, sm},
})
```
@@ -502,4 +506,4 @@ Important:
> 💡
-> Skill Middleware 仅提供了如上图所示的加载 SKILL.md 能力,如果 Skill 本身需要读取文件、执行脚本等,需要用户另外为 agent 配置相关能力。
+> Skill Middleware 仅提供了如上图所示的加载 SKILL.md 能力,如果 Skill 需要 agent 具备读取文件、执行脚本等能力,需要用户另外为 agent 配置。
diff --git a/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_ToolReduction.md b/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_ToolReduction.md
index 309c9ab004c..fae42a03c9a 100644
--- a/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_ToolReduction.md
+++ b/content/zh/docs/eino/core_modules/eino_adk/Eino_ADK_ChatModelAgentMiddleware/Middleware_ToolReduction.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-09"
+date: "2026-03-12"
lastmod: ""
tags: []
title: Reduction
diff --git a/content/zh/docs/eino/core_modules/eino_adk/adk_agent_callback.md b/content/zh/docs/eino/core_modules/eino_adk/adk_agent_callback.md
index 1088b50d6f4..90b1d677e6c 100644
--- a/content/zh/docs/eino/core_modules/eino_adk/adk_agent_callback.md
+++ b/content/zh/docs/eino/core_modules/eino_adk/adk_agent_callback.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-10"
+date: "2026-03-12"
lastmod: ""
tags: []
title: Agent Callback
diff --git a/content/zh/docs/eino/core_modules/eino_adk/agent_implementation/chat_model.md b/content/zh/docs/eino/core_modules/eino_adk/agent_implementation/chat_model.md
index 960e06f1c61..381c85fb092 100644
--- a/content/zh/docs/eino/core_modules/eino_adk/agent_implementation/chat_model.md
+++ b/content/zh/docs/eino/core_modules/eino_adk/agent_implementation/chat_model.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-03-09"
+date: "2026-03-16"
lastmod: ""
tags: []
title: ChatModelAgent
diff --git a/content/zh/docs/eino/core_modules/eino_adk/agent_preview.md b/content/zh/docs/eino/core_modules/eino_adk/agent_preview.md
index 6a26a9a3ef5..c3c846c2328 100644
--- a/content/zh/docs/eino/core_modules/eino_adk/agent_preview.md
+++ b/content/zh/docs/eino/core_modules/eino_adk/agent_preview.md
@@ -145,7 +145,7 @@ AgentRunner 是 Agent 的执行器,为 Agent 运行所需要的拓展功能加
只有通过 Runner 执行 agent 时,才可以使用 ADK 的如下功能:
- Interrupt & Resume
-- 切面机制(测试版本支持,正式发布前不保证 API 兼容)
+- 切面机制(测试版本支持,正式发布前不保证 API 兼容,详见 Agent 扩展章节)
- Context 环境的预处理
```go
diff --git a/content/zh/docs/eino/core_modules/flow_integration_components/react_agent_manual.md b/content/zh/docs/eino/core_modules/flow_integration_components/react_agent_manual.md
index 26414457651..761f9bf5116 100644
--- a/content/zh/docs/eino/core_modules/flow_integration_components/react_agent_manual.md
+++ b/content/zh/docs/eino/core_modules/flow_integration_components/react_agent_manual.md
@@ -1,6 +1,6 @@
---
Description: ""
-date: "2026-01-30"
+date: "2026-03-16"
lastmod: ""
tags: []
title: ReAct Agent 使用手册
diff --git a/content/zh/docs/eino/ecosystem_integration/_index.md b/content/zh/docs/eino/ecosystem_integration/_index.md
index ca3673709af..1dcb09ae790 100644
--- a/content/zh/docs/eino/ecosystem_integration/_index.md
+++ b/content/zh/docs/eino/ecosystem_integration/_index.md
@@ -11,9 +11,9 @@ weight: 6
### ChatModel
-- openai: [ChatModel - OpenAI](https://github.com/cloudwego/eino-ext/blob/main/components/model/openai/README_zh.md)
-- ark: [ChatModel - ARK](https://github.com/cloudwego/eino-ext/blob/main/components/model/ark/README_zh.md)
-- ollama: [ChatModel - Ollama](https://github.com/cloudwego/eino-ext/blob/main/components/model/ollama/README_zh.md)
+- openai: [OpenAI](/zh/docs/eino/ecosystem_integration/chat_model/agentic_model_openai)
+- ark: [ARK](/zh/docs/eino/ecosystem_integration/chat_model/agentic_model_ark)
+- 更多组件请见:[ChatModel 组件列表](/zh/docs/eino/ecosystem_integration/chat_model)
### Document
diff --git a/content/zh/docs/eino/quick_start/_index.md b/content/zh/docs/eino/quick_start/_index.md
index 78ae777d858..9333db3afd1 100644
--- a/content/zh/docs/eino/quick_start/_index.md
+++ b/content/zh/docs/eino/quick_start/_index.md
@@ -1,39 +1,101 @@
---
Description: ""
-date: "2025-11-20"
+date: "2026-03-16"
lastmod: ""
tags: []
title: 快速开始
weight: 2
---
-## 简要说明
+本篇文档用于作为 ChatWithEino Quickstart 的统一入口:用一条清晰的路径带你跑起来,并解释这个系列最终要交付什么(一个可扩展的端到端 Agent 应用骨架)。
-Eino 提供了多种面向 AI 应用开发场景的组件抽象,同时也提供了多种实现,因此用 Eino 快速上手开发一个应用是**非常简单**的。本目录中将提供几个最常见的用 AI 搭建的应用实例,以帮助你快速地上手使用 Eino。
+## 这是什么
-这几个小应用仅用于快速上手,对于其中的单项能力的更详细介绍及示例,可以参考 [组件介绍](/zh/docs/eino/core_modules/components)、[编排介绍](/zh/docs/eino/core_modules/chain_and_graph_orchestration/chain_graph_introduction) 等专题文档。
+ChatWithEino 是一个基于 Eino 构建的学习型 Agent:它能读取源码/文档/示例,并通过对话帮助开发者理解 Eino 以及用 Eino 写代码。
-## 快速开始示例
+这个 Quickstart 系列采用“渐进式搭建”的方式:
-### 示例:LLM 最简应用
+- 前期以 Console 为载体,逐步引入 ChatModel、Agent/Runner、Memory、Tool、Middleware、Callback、Interrupt/Resume、Graph Tool、Skill
+- 最终把同一个 Agent 以 Web 形态交付出来,并用 A2UI 协议把事件流渲染成可增量更新的 UI
-AI 的应用中,最基础的场景就是 prompt + chat model 的场景,这也是互联网上各类 AI 应用平台提供的最重要的功能。你可以定义 `System Prompt` 来约束大模型的回答逻辑,比如 “你在扮演一个 XXX 角色” 等等。这个示例中,你可以用 Eino 的 `PromptTemplate` 组件 和 `ChatModel` 组件来构建一个角色扮演应用。
+## 最短路径:先跑起来
-- [实现一个最简 LLM 应用-ChatModel](/zh/docs/eino/quick_start/simple_llm_application)
+在仓库根目录执行:
-### 示例:创建一个 Agent
+```bash
+git clone https://github.com/cloudwego/eino-examples.git
+cd eino-examples/quickstart/chatwitheino
+```
-大模型是 AI 的大脑,其核心是理解自然语言,并做出回应,(文本)大模型本身只能接收一段文本,然后输出一段文本。而当你希望大模型能使用一些工具自行获取所需的信息、执行一些动作,就需要使用 `Tool` 来实现了,拥有了 Tool 的大模型就像是拥有了手脚,可以和当下已有的 IT 基础设施进行交互,比如 "调用 http 接口查询天气,再根据天气提醒你今天要传什么衣服",就需要大模型调用 "search tool" 查询信息。
+### 1) 最小 Console(第一章)
-我们通常把能够根据大模型的输出调用相关 tool 的这套体系所构建出的整体,叫做 “智能体”,即 Agent。
+准备模型配置(以 OpenAI 为例):
-在 Eino 中,你可以单独使用 ChatModel + ToolsNode 来实现 Agent,也可以使用封装好的 `react agent` 和 `multi agent`。
+```bash
+export OPENAI_API_KEY="..."
+export OPENAI_MODEL="gpt-4.1-mini"
+```
-在这个示例中,我们将使用 react agent 来构建一个可以和现实世界交互的智能体。
+运行:
-- [Agent-让大模型拥有双手](/zh/docs/eino/quick_start/agent_llm_with_tools)
+```bash
+go run ./cmd/ch01 -- "用一句话解释 Eino 的 Component 设计解决了什么问题?"
+```
-## 下一步探索
+### 2) 最终 Web(A2UI)
-- 理解 Eino 的核心模块和概念: [Eino: 核心模块](/zh/docs/eino/core_modules),这是你自如玩转使用 Eino 做应用开发的关键信息。
-- Eino 保持开放生态的姿态,提供了大量生态集成组件:[Eino: 生态集成](/zh/docs/eino/ecosystem_integration),你可以使用这些组件快速构建自己的业务应用。
+```bash
+go run .
+```
+
+启动后访问输出里的地址(默认 `http://localhost:8080`)。
+
+### 3) (可选)开启 skills(第九章能力复用)
+
+skills 用于把一组稳定的“知识/指令包”(`SKILL.md` + `reference/*.md`)注入到 Agent,让模型在需要时按需加载并调用。
+
+```bash
+go run ./scripts/sync_eino_ext_skills.go -src /path/to/eino-ext -dest ./skills/eino-ext -clean
+EINO_EXT_SKILLS_DIR="$(pwd)/skills/eino-ext" go run .
+```
+
+说明:
+
+- `./skills/` 目录默认被 `.gitignore` 忽略,避免把同步出来的 skills 误提交
+- 如需验证 Skill 是否生效,可运行第九章示例入口代码:
+ - [https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch09/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch09/main.go)
+
+## 学习路线(章节导航)
+
+
+| 章节 | 主题 | 入口 |
+| 第一章 | ChatModel 与 Message(Console) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch01_chatmodel_agent_console.md |
+| 第二章 | Agent 与 Runner(Console 多轮) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch02_chatmodel_agent_runner_console.md |
+| 第三章 | Memory 与 Session(持久化对话) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch03_memory_session_jsonl.md |
+| 第四章 | Tool 与文件系统访问 | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch04_tool_backend_filesystem.md |
+| 第五章 | Middleware(中间件模式) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch05_middleware.md |
+| 第六章 | Callback 与 Trace(可观测性) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch06_callback.md |
+| 第七章 | Interrupt/Resume(中断与恢复) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch07_interrupt_resume.md |
+| 第八章 | Graph Tool(复杂工作流) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch08_graph_tool.md |
+| 第九章 | Skill(Console) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch09_skill.md |
+| 最终章 | A2UI(Web) | https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/docs/ch10_a2ui.md |
+
+
+## 最终交付:一个可扩展的端到端 Agent 应用骨架
+
+你可以把这个 Quickstart 的最终产物理解为一套“可插拔的应用骨架”,它把 Eino 的关键能力连成闭环:
+
+- 运行时:Runner 驱动执行,支持流式输出与事件模型
+- 工具层:通过 Tool 接入文件系统/检索/工作流等能力
+- 中间件:用 handler/middleware 承载重试、审批、错误处理等横切能力
+- 人机协作:interrupt/resume + checkpoint 支持审批、补参、分支选择等交互式流程
+- 确定性编排:compose(graph/chain/workflow)把复杂业务流程组织为可维护、可复用的执行图
+- UI 交付:用 A2UI 把 Agent 的事件流映射为可增量渲染的 UI 组件树(SSE 推送)
+
+其中 A2UI 的边界需要明确:它不是 Eino 框架本身的一部分,而是业务层的 UI 协议/渲染方案。本 Quickstart 用它来展示“Agent 能力如何以产品形态呈现给用户”,具体实现与协议细节以最终章为准。
+
+## 下一步探索(从 Quickstart 到真实业务)
+
+- 想系统理解 Eino 的组件抽象与用法:从第一章的 Component 入门开始,再按章节逐步补齐 Tool/Graph/Callback/Interrupt 等能力
+- 想复用更大规模的知识与指令:对接 `eino-ext` 的 skills,并通过 Skill 中间件按需加载
+- 想把 Agent 做成业务产品:参考最终章(A2UI/Web)把事件流、状态与交互打通,再替换为你自己的 UI 形态与协议
diff --git a/content/zh/docs/eino/quick_start/agent_llm_with_tools.md b/content/zh/docs/eino/quick_start/agent_llm_with_tools.md
deleted file mode 100644
index 2694ed87a92..00000000000
--- a/content/zh/docs/eino/quick_start/agent_llm_with_tools.md
+++ /dev/null
@@ -1,300 +0,0 @@
----
-Description: ""
-date: "2026-03-03"
-lastmod: ""
-tags: []
-title: Agent-让大模型拥有双手
-weight: 2
----
-
-## **Agent 是什么**
-
-Agent(智能代理)是一个能够感知环境并采取行动以实现特定目标的系统。在 AI 应用中,Agent 通过结合大语言模型的理解能力和预定义工具的执行能力,可以自主地完成复杂的任务。是未来 AI 应用到生活生产中主要的形态。
-
-> 💡
-> 本文中示例的代码片段详见:[eino-examples/quickstart/todoagent](https://github.com/cloudwego/eino-examples/blob/master/quickstart/todoagent/main.go)
-
-## **Agent 的核心组成**
-
-在 Eino 中,要实现 Agent 主要需要两个核心部分:ChatModel 和 Tool。
-
-### **ChatModel**
-
-ChatModel 是 Agent 的大脑,它通过强大的语言理解能力来处理用户的自然语言输入。当用户提出请求时,ChatModel 会深入理解用户的意图,分析任务需求,并决定是否需要调用特定的工具来完成任务。在需要使用工具时,它能够准确地选择合适的工具并生成正确的参数。不仅如此,ChatModel 还能将工具执行的结果转化为用户易于理解的自然语言回应,实现流畅的人机对话。
-
-> 更详细的 ChatModel 的信息,可以参考: [Eino: ChatModel 使用说明](/zh/docs/eino/core_modules/components/chat_model_guide)
-
-### **Tool**
-
-Tool 是 Agent 的执行器,提供了具体的功能实现。每个 Tool 都有明确的功能定义和参数规范,使 ChatModel 能够准确地调用它们。Tool 可以实现各种功能,从简单的数据操作到复杂的外部服务调用都可以封装成 Tool。
-
-> 更详细关于 Tool 和 ToolsNode 的信息,可参考: [Eino: ToolsNode 使用说明](/zh/docs/eino/core_modules/components/tools_node_guide)
-
-## **Tool 的实现方式**
-
-在 Eino 中,我们提供了多种方式来实现 Tool。下面通过一个待办事项(Todo)管理系统的例子来说明。
-
-### **方式一:使用 NewTool 构建**
-
-这种方式适合简单的工具实现,通过定义工具信息和处理函数来创建 Tool:
-
-```go
-import (
- "context"
-
- "github.com/cloudwego/eino/components/tool"
- "github.com/cloudwego/eino/components/tool/utils"
- "github.com/cloudwego/eino/schema"
-)
-
-// 处理函数
-func AddTodoFunc(_ context.Context, params *TodoAddParams) (string, error) {
- // Mock处理逻辑
- return `{"msg": "add todo success"}`, nil
-}
-
-func getAddTodoTool() tool.InvokableTool {
- // 工具信息
- info := &schema.ToolInfo{
- Name: "add_todo",
- Desc: "Add a todo item",
- ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
- "content": {
- Desc: "The content of the todo item",
- Type: schema.String,
- Required: true,
- },
- "started_at": {
- Desc: "The started time of the todo item, in unix timestamp",
- Type: schema.Integer,
- },
- "deadline": {
- Desc: "The deadline of the todo item, in unix timestamp",
- Type: schema.Integer,
- },
- }),
- }
-
- // 使用NewTool创建工具
- return utils.NewTool(info, AddTodoFunc)
-}
-```
-
-这种方式虽然直观,但存在一个明显的缺点:需要在 ToolInfo 中手动定义参数信息(ParamsOneOf),和实际的参数结构(TodoAddParams)是分开定义的。这样不仅造成了代码的冗余,而且在参数发生变化时需要同时修改两处地方,容易导致不一致,维护起来也比较麻烦。
-
-### **方式二:使用 InferTool 构建**
-
-这种方式更加简洁,通过结构体的 tag 来定义参数信息,就能实现参数结构体和描述信息同源,无需维护两份信息:
-
-```go
-import (
- "context"
-
- "github.com/cloudwego/eino/components/tool/utils"
-)
-
-// 参数结构体
-type TodoUpdateParams struct {
- ID string `json:"id" jsonschema:"description=id of the todo"`
- Content *string `json:"content,omitempty" jsonschema:"description=content of the todo"`
- StartedAt *int64 `json:"started_at,omitempty" jsonschema:"description=start time in unix timestamp"`
- Deadline *int64 `json:"deadline,omitempty" jsonschema:"description=deadline of the todo in unix timestamp"`
- Done *bool `json:"done,omitempty" jsonschema:"description=done status"`
-}
-
-// 处理函数
-func UpdateTodoFunc(_ context.Context, params *TodoUpdateParams) (string, error) {
- // Mock处理逻辑
- return `{"msg": "update todo success"}`, nil
-}
-
-// 使用 InferTool 创建工具
-updateTool, err := utils.InferTool(
- "update_todo", // tool name
- "Update a todo item, eg: content,deadline...", // tool description
- UpdateTodoFunc)
-```
-
-### **方式三:实现 Tool 接口**
-
-对于需要更多自定义逻辑的场景,可以通过实现 Tool 接口来创建:
-
-```go
-import (
- "context"
-
- "github.com/cloudwego/eino/components/tool"
- "github.com/cloudwego/eino/schema"
-)
-
-type ListTodoTool struct {}
-
-func (lt *ListTodoTool) Info(ctx context.Context) (*schema.ToolInfo, error) {
- return &schema.ToolInfo{
- Name: "list_todo",
- Desc: "List all todo items",
- ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
- "finished": {
- Desc: "filter todo items if finished",
- Type: schema.Boolean,
- Required: false,
- },
- }),
- }, nil
-}
-
-func (lt *ListTodoTool) InvokableRun(ctx context.Context, argumentsInJSON string, opts ...tool.Option) (string, error) {
- // Mock调用逻辑
- return `{"todos": [{"id": "1", "content": "在2024年12月10日之前完成Eino项目演示文稿的准备工作", "started_at": 1717401600, "deadline": 1717488000, "done": false}]}`, nil
-}
-```
-
-### **方式四:使用****官方封装的工具**
-
-除了自己实现工具,我们还提供了许多开箱即用的工具。这些工具经过充分测试和优化,可以直接集成到你的 Agent 中。以 duckduckgo Search 工具为例:
-
-```go
-import (
- "github.com/cloudwego/eino-ext/components/tool/duckduckgo"
-)
-
-
-// 创建 duckduckgo Search 工具
-searchTool, err := duckduckgo.NewTool(ctx, &duckduckgo.Config{})
-```
-
-使用 eino-ext 提供的工具不仅能避免重复开发的工作量,还能确保工具的稳定性和可靠性。这些工具都经过充分测试和持续维护,可以直接集成到项目中使用。
-
-## **用 Chain 构建 Agent**
-
-在构建 Agent 时,ToolsNode 是一个核心组件,它负责管理和执行工具调用。ToolsNode 可以集成多个工具,并提供统一的调用接口。它支持同步调用(Invoke)和流式调用(Stream)两种方式,能够灵活地处理不同类型的工具执行需求。
-
-要创建一个 ToolsNode,你需要提供一个工具列表配置:
-
-```go
-import (
- "context"
-
- "github.com/cloudwego/eino/components/tool"
- "github.com/cloudwego/eino/compose"
-)
-
-conf := &compose.ToolsNodeConfig{
- Tools: []tool.BaseTool{tool1, tool2}, // 工具可以是 InvokableTool 或 StreamableTool
-}
-toolsNode, err := compose.NewToolNode(context.Background(), conf)
-```
-
-下面是一个完整的 Agent 示例,它使用 OpenAI 的 ChatModel 并结合了上述的 Todo 工具:
-
-```go
-import (
- "context"
- "fmt"
- "log"
- "os"
-
- "github.com/cloudwego/eino-ext/components/model/openai"
- "github.com/cloudwego/eino/components/tool"
- "github.com/cloudwego/eino/compose"
- "github.com/cloudwego/eino/schema"
-)
-
-func main() {
- // 初始化 tools
- todoTools := []tool.BaseTool{
- getAddTodoTool(), // NewTool 构建
- updateTool, // InferTool 构建
- &ListTodoTool{}, // 实现Tool接口
- searchTool, // 官方封装的工具
- }
-
- // 创建并配置 ChatModel
- chatModel, err := openai.NewChatModel(context.Background(), &openai.ChatModelConfig{
- Model: "gpt-4",
- APIKey: os.Getenv("OPENAI_API_KEY"),
- })
- if err != nil {
- log.Fatal(err)
- }
- // 获取工具信息并绑定到 ChatModel
- toolInfos := make([]*schema.ToolInfo, 0, len(todoTools))
- for _, tool := range todoTools {
- info, err := tool.Info(ctx)
- if err != nil {
- log.Fatal(err)
- }
- toolInfos = append(toolInfos, info)
- }
- err = chatModel.BindTools(toolInfos)
- if err != nil {
- log.Fatal(err)
- }
-
-
- // 创建 tools 节点
- todoToolsNode, err := compose.NewToolNode(context.Background(), &compose.ToolsNodeConfig{
- Tools: todoTools,
- })
- if err != nil {
- log.Fatal(err)
- }
-
- // 构建完整的处理链
- chain := compose.NewChain[[]*schema.Message, []*schema.Message]()
- chain.
- AppendChatModel(chatModel, compose.WithNodeName("chat_model")).
- AppendToolsNode(todoToolsNode, compose.WithNodeName("tools"))
-
- // 编译并运行 chain
- agent, err := chain.Compile(ctx)
- if err != nil {
- log.Fatal(err)
- }
-
- // 运行示例
- resp, err := agent.Invoke(ctx, []*schema.Message{
- {
- Role: schema.User,
- Content: "添加一个学习 Eino 的 TODO,同时搜索一下 cloudwego/eino 的仓库地址",
- },
- })
- if err != nil {
- log.Fatal(err)
- }
-
- // 输出结果
- for _, msg := range resp {
- fmt.Println(msg.Content)
- }
-}
-```
-
-这个示例有一个假设,也就是 ChatModel 一定会做出 tool 调用的决策。
-
-## **使用其他方式构建 Agent**
-
-除了上述使用 Chain/Graph 构建的 agent 之外,Eino 还提供了常用的 Agent 模式的封装。
-
-### **ReAct Agent**
-
-ReAct(Reasoning + Acting)Agent 结合了推理和行动能力,通过思考-行动-观察的循环来解决复杂问题。它能够在执行任务时进行深入的推理,并根据观察结果调整策略,特别适合需要多步推理的复杂场景。
-
-> 更详细的 react agent 可以参考: [Eino: React Agent 使用手册](/zh/docs/eino/core_modules/flow_integration_components/react_agent_manual)
-
-### **Multi Agent**
-
-Multi Agent 系统由多个协同工作的 Agent 组成,每个 Agent 都有其特定的职责和专长。通过 Agent 间的交互与协作,可以处理更复杂的任务,实现分工协作。这种方式特别适合需要多个专业领域知识结合的场景。
-
-> 更详细的 multi agent 可以参考: [Eino Tutorial: Host Multi-Agent ](/zh/docs/eino/core_modules/flow_integration_components/multi_agent_hosting)
-
-## **总结**
-
-介绍了使用 Eino 框架构建 Agent 的基本方法。通过 Chain、Tool Calling 和 ReAct 等不同方式,我们可以根据实际需求灵活地构建 AI Agent。
-
-Agent 是 AI 技术发展的重要方向。它不仅能够理解用户意图,还能主动采取行动,通过调用各种工具来完成复杂任务。随着大语言模型能力的不断提升,Agent 将在未来扮演越来越重要的角色,成为连接 AI 与现实世界的重要桥梁。我们期待 Eino 能为用户带来更强大、易用的 agent 构建方案,推动更多基于 Agent 的应用创新。
-
-## **关联阅读**
-
-- 快速开始
- - [实现一个最简 LLM 应用-ChatModel](/zh/docs/eino/quick_start/simple_llm_application)
diff --git a/content/zh/docs/eino/quick_start/chapter_01_chatmodel_and_message.md b/content/zh/docs/eino/quick_start/chapter_01_chatmodel_and_message.md
new file mode 100644
index 00000000000..e961e52b1be
--- /dev/null
+++ b/content/zh/docs/eino/quick_start/chapter_01_chatmodel_and_message.md
@@ -0,0 +1,222 @@
+---
+Description: ""
+date: "2026-03-12"
+lastmod: ""
+tags: []
+title: 第一章:ChatModel 与 Message(Console)
+weight: 1
+---
+
+## Eino 框架简介
+
+**Eino 是什么?**
+
+Eino 是一个 Go 语言实现的 AI 应用开发框架(Agent Development Kit),旨在帮助开发者快速构建可扩展、可维护的 AI 应用。
+
+**Eino 解决什么问题?**
+
+1. **模型抽象**:统一不同 LLM 提供商的接口(OpenAI、Ark、Claude 等),切换模型无需修改业务代码
+2. **能力组合**:通过 Component 接口实现可替换、可组合的能力单元(对话、工具、检索等)
+3. **编排框架**:提供 Agent、Graph、Chain 等编排抽象,支持复杂的多步骤 AI 工作流
+4. **运行时支持**:内置流式输出、中断与恢复、状态管理、Callback 可观测性等能力
+
+**Eino 的主要仓库:**
+
+- **eino**(本仓库):核心库,定义接口、编排抽象和 ADK
+- **eino-ext**:扩展库,提供各类 Component 的具体实现(OpenAI、Ark、Milvus 等)
+- **eino-examples**:示例代码库,包含本 quickstart 系列
+
+---
+
+## ChatWithEino:与 Eino 文档对话的智能助手
+
+**ChatWithEino 是什么?**
+
+ChatWithEino 是一个基于 Eino 框架构建的智能助手,能够帮助开发者学习 Eino 框架并编写 Eino 代码。它通过访问 Eino 仓库的源码、注释和示例,为用户提供最准确、最及时的技术支持。
+
+**核心能力:**
+
+- **对话交互**:理解用户关于 Eino 的问题,提供清晰的解答
+- **代码访问**:直接读取 Eino 源码、注释和示例,基于真实实现回答问题
+- **持久化会话**:支持多轮对话,记住上下文,可跨进程恢复会话
+- **工具调用**:能够执行文件读取、代码搜索等操作
+
+**技术架构:**
+
+- **ChatModel**:与大语言模型通信(OpenAI、Ark、Claude 等)
+- **Tool**:文件系统访问、代码搜索等能力扩展
+- **Memory**:对话历史持久化存储
+- **Agent**:统一的执行框架,协调各组件协同工作
+
+## Quickstart 文档系列:从零构建 ChatWithEino
+
+本系列文档通过循序渐进的方式,带你从最基础的 ChatModel 调用开始,逐步构建一个功能完整的 ChatWithEino Agent。
+
+**学习路径:**
+
+
+| 章节 | 主题 | 核心内容 | 能力提升 |
+| 第一章 | ChatModel 与 Message | 理解 Component 抽象,实现单次对话 | 基础对话能力 |
+| 第二章 | Agent 与 Runner | 引入执行抽象,实现多轮对话 | 会话管理能力 |
+| 第三章 | Memory 与 Session | 持久化对话历史,支持会话恢复 | 持久化能力 |
+| 第四章 | Tool 与文件系统 | 添加文件访问能力,读取源码 | 工具调用能力 |
+| 第五章 | Middleware | 中间件机制,统一处理横切关注点 | 扩展性增强 |
+| 第六章 | Callback | 回调机制,监控 Agent 执行过程 | 可观测性 |
+| 第七章 | Interrupt 与 Resume | 中断与恢复,支持长时间任务 | 可靠性增强 |
+| 第八章 | Graph 与 Tool | 使用 Graph 编排复杂工作流 | 复杂编排能力 |
+| 第九章 | A2UI | Agent 到 UI 的集成方案 | 生产级应用 |
+
+
+**为什么这样设计?**
+
+每一章都在前一章的基础上增加一个核心能力,让你:
+
+1. **理解每个组件的作用**:不是一次性展示所有功能,而是逐步引入
+2. **看到架构演进过程**:从简单到复杂,理解为什么需要每个抽象
+3. **掌握实际开发技能**:每章都有可运行的代码,可以动手实践
+
+---
+
+本章目标:理解 Eino 的 Component 抽象,用最小代码调用一次 ChatModel(支持流式输出),并掌握 `schema.Message` 的基本用法。
+
+## 代码位置
+
+- 入口代码:[cmd/ch01/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch01/main.go)
+
+## 为什么需要 Component 接口
+
+Eino 定义了一组 Component 接口(`ChatModel`、`Tool`、`Retriever`、`Loader` 等),每个接口描述一类可替换的能力:
+
+```go
+type BaseChatModel interface {
+ Generate(ctx context.Context, input []*schema.Message, opts ...Option) (*schema.Message, error)
+ Stream(ctx context.Context, input []*schema.Message, opts ...Option) (
+ *schema.StreamReader[*schema.Message], error)
+}
+```
+
+**接口带来的好处:**
+
+1. **实现可替换**:`eino-ext` 提供了 OpenAI、Ark、Claude、Ollama 等多种实现,业务代码只依赖接口,切换模型只需改构造逻辑。
+2. **编排可组合**:Agent、Graph、Chain 等编排层只依赖 Component 接口,不关心具体实现。你可以把 OpenAI 换成 Ark,编排代码无需改动。
+3. **测试可 Mock**:接口天然支持 mock,单元测试不需要真实调用模型。
+
+本章只涉及 `ChatModel`,后续章节会逐步引入 `Tool`、`Retriever` 等 Component。
+
+## schema.Message:对话的基本单位
+
+`Message` 是 Eino 里对话数据的基本结构:
+
+```go
+type Message struct {
+ Role RoleType // system / user / assistant / tool
+ Content string // 文本内容
+ ToolCalls []ToolCall // 仅 assistant 消息可能有
+ // ...
+}
+```
+
+常用构造函数:
+
+```go
+schema.SystemMessage("You are a helpful assistant.")
+schema.UserMessage("What is the weather today?")
+schema.AssistantMessage("I don't know.", nil) // 第二个参数是 ToolCalls
+schema.ToolMessage("tool result", "call_id")
+```
+
+**角色语义:**
+
+- `system`:系统指令,通常放在 messages 最前面
+- `user`:用户输入
+- `assistant`:模型回复
+- `tool`:工具调用结果(后续章节涉及)
+
+## 前置条件
+
+### 获取代码
+
+```bash
+git clone https://github.com/cloudwego/eino-examples.git
+cd eino-examples/quickstart/chatwitheino
+```
+
+- Go 版本:Go 1.21+(见 `go.mod`)
+- 一个可调用的 ChatModel(默认使用 OpenAI;也支持 Ark)
+
+### 方式 A:OpenAI(默认)
+
+```bash
+export OPENAI_API_KEY="..."
+export OPENAI_MODEL="gpt-4.1-mini" # OpenAI 2025 年新模型,也可用 gpt-4o、gpt-4o-mini 等
+# 可选:
+# OPENAI_BASE_URL(代理或兼容服务)
+# OPENAI_BY_AZURE=true(使用 Azure OpenAI)
+```
+
+### 方式 B:Ark
+
+```bash
+export MODEL_TYPE="ark"
+export ARK_API_KEY="..."
+export ARK_MODEL="..."
+# 可选:ARK_BASE_URL
+```
+
+## 运行
+
+在 `examples/quickstart/chatwitheino` 目录下执行:
+
+```bash
+go run ./cmd/ch01 -- "用一句话解释 Eino 的 Component 设计解决了什么问题?"
+```
+
+输出示例(流式逐步打印):
+
+```
+[assistant] Eino 的 Component 设计通过定义统一接口...
+```
+
+## 入口代码做了什么
+
+按执行顺序:
+
+1. **创建 ChatModel**:根据 `MODEL_TYPE` 环境变量选择 OpenAI 或 Ark 实现
+2. **构造输入 messages**:`SystemMessage(instruction)` + `UserMessage(query)`
+3. **调用 Stream**:所有 ChatModel 实现都必须支持 `Stream()`,返回 `StreamReader[*Message]`
+4. **打印结果**:迭代 `StreamReader` 逐帧打印 assistant 回复
+
+关键代码片段(**注意:这是简化后的代码片段,不能直接运行****,完整代码请参考** [cmd/ch01/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch01/main.go)):
+
+```go
+// 构造输入
+messages := []*schema.Message{
+ schema.SystemMessage(instruction),
+ schema.UserMessage(query),
+}
+
+// 调用 Stream(所有 ChatModel 都必须实现)
+stream, err := cm.Stream(ctx, messages)
+if err != nil {
+ log.Fatal(err)
+}
+defer stream.Close()
+
+for {
+ chunk, err := stream.Recv()
+ if errors.Is(err, io.EOF) {
+ break
+ }
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Print(chunk.Content)
+}
+```
+
+## 本章小结
+
+- **Component 接口**:定义可替换、可组合、可测试的能力边界
+- **Message**:对话数据的基本单位,通过角色区分语义
+- **ChatModel**:最基础的 Component,提供 `Generate` 和 `Stream` 两个核心方法
+- **实现选择**:通过环境变量或配置切换 OpenAI/Ark 等不同实现,业务代码无需改动
diff --git a/content/zh/docs/eino/quick_start/chapter_02_chatmodelagent_runner_agentevent.md b/content/zh/docs/eino/quick_start/chapter_02_chatmodelagent_runner_agentevent.md
new file mode 100644
index 00000000000..e7360cf64db
--- /dev/null
+++ b/content/zh/docs/eino/quick_start/chapter_02_chatmodelagent_runner_agentevent.md
@@ -0,0 +1,309 @@
+---
+Description: ""
+date: "2026-03-12"
+lastmod: ""
+tags: []
+title: 第二章:ChatModelAgent、Runner、AgentEvent(Console 多轮)
+weight: 2
+---
+
+本章目标:引入 ADK 的执行抽象(Agent + Runner),并用一个 Console 程序实现多轮对话。
+
+## 代码位置
+
+- 入口代码:[cmd/ch02/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch02/main.go)
+
+## 前置条件
+
+与第一章一致:需要配置一个可用的 ChatModel(OpenAI 或 Ark)。
+
+## 运行
+
+在 `examples/quickstart/chatwitheino` 目录下执行:
+
+```bash
+go run ./cmd/ch02
+```
+
+看到提示后输入问题(空行退出):
+
+```
+you> 你好,解释一下 Eino 里的 Agent 是什么?
+...
+you> 再用一句话总结一下
+...
+```
+
+## 关键概念
+
+### 从 Component 到 Agent
+
+第一章我们学习了 **Component**(组件),它是 Eino 中可替换、可组合的能力单元:
+
+- `ChatModel`:调用大语言模型
+- `Tool`:执行特定任务
+- `Retriever`:检索信息
+- `Loader`:加载数据
+
+**Component 和 Agent 的关系:**
+
+- **Component 不构成完整的 AI 应用**:它只是能力单元,需要被组织、编排、执行
+- **Agent 是完整的 AI 应用**:它封装了完整的业务逻辑,可以直接运行
+- **Agent 内部使用 Component**:最核心的是 `ChatModel`(对话能力)和 `Tool`(执行能力)
+
+**为什么需要 Agent?**
+
+如果只有 Component,你需要自己:
+
+- 管理对话历史
+- 编排调用流程(何时调用模型、何时调用工具)
+- 处理流式输出
+- 实现中断恢复
+- ...
+
+**Agent 提供了什么?**
+
+- **完整的运行时框架**:通过 `Runner` 统一管理执行过程
+- **标准的事件流输出**:`Run() -> AsyncIterator[*AgentEvent]`,支持流式、中断、恢复
+- **可扩展能力**:可以添加 tools、middleware、interrupt 等
+- **开箱即用**:创建 Agent 后直接运行,无需关心内部细节
+
+**本章示例:**
+
+`ChatModelAgent` 是最简单的 Agent,它内部只使用了 `ChatModel`,但已经具备了 Agent 的完整能力框架。后续章节会展示如何添加 `Tool` 等更多能力。
+
+### Agent 接口
+
+`Agent` 是 ADK 中的核心接口,定义了智能体的基本行为:
+
+```go
+type Agent interface {
+ Name(ctx context.Context) string
+ Description(ctx context.Context) string
+
+ // Run 执行 Agent,返回事件流
+ Run(ctx context.Context, input *AgentInput, options ...AgentRunOption) *AsyncIterator[*AgentEvent]
+}
+```
+
+**接口职责:**
+
+- `Name()` / `Description()`:标识 Agent 的名称和描述
+- `Run()`:执行 Agent 的核心方法,接收输入消息,返回事件流
+
+**设计理念:**
+
+- **统一抽象**:所有 Agent(ChatModelAgent、WorkflowAgent、SupervisorAgent 等)都实现这个接口
+- **事件驱动**:通过事件流(`AsyncIterator[*AgentEvent]`)输出执行过程,支持流式响应
+- **可扩展性**:后续加入 tools、middleware、interrupt 等能力时,接口保持不变
+
+### ChatModelAgent
+
+`ChatModelAgent` 是 Agent 接口的一个实现,基于 ChatModel 构建:
+
+```go
+agent, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
+ Name: "Ch02ChatModelAgent",
+ Description: "A minimal ChatModelAgent with in-memory multi-turn history.",
+ Instruction: instruction,
+ Model: cm,
+})
+```
+
+**ChatModel vs ChatModelAgent:本质区别**
+
+
+| 维度 | ChatModel | ChatModelAgent |
+| 定位 | Component(组件) | Agent(智能体) |
+| 接口 | Generate() / Stream() | Run() -> AsyncIterator[*AgentEvent] |
+| 输出 | 直接返回消息内容 | 返回事件流(包含消息、控制动作等) |
+| 能力 | 单纯的模型调用 | 可扩展 tools、middleware、interrupt 等 |
+| 适用场景 | 简单的对话场景 | 复杂的智能体应用 |
+
+
+**为什么需要 ChatModelAgent?**
+
+1. **统一抽象**:ChatModel 只是 Component 的一种,而 Agent 是更高层的抽象,可以组合多种 Component
+2. **事件驱动**:Agent 输出事件流,支持流式响应、中断恢复、状态转移等复杂场景
+3. **可扩展性**:ChatModelAgent 可以添加 tools、middleware、interrupt 等能力,而 ChatModel 只能调用模型
+4. **编排友好**:Agent 可以被 Runner 统一管理,支持 checkpoint、恢复等运行时能力
+
+**简单来说:**
+
+- **ChatModel** = "负责与大语言模型通信的组件,屏蔽不同模型提供商的差异(OpenAI、Ark、Claude 等)"
+- **ChatModelAgent** = "基于模型构建的智能体,可以调用模型,但还能做更多事"
+
+**类比理解:**
+
+- **ChatModel** 就像"数据库驱动":负责与数据库通信,屏蔽 MySQL/PostgreSQL 的差异
+- **ChatModelAgent** 就像"业务逻辑层":基于数据库驱动构建,但还包含业务规则、事务管理等
+
+**特点:**
+
+- 封装了 ChatModel 的调用逻辑
+- 提供统一的 `Run() -> AgentEvent` 输出形态
+- 后续可以添加 tools、middleware 等能力
+
+### Runner
+
+`Runner` 是执行 Agent 的入口点,负责管理 Agent 的生命周期:
+
+```go
+type Runner struct {
+ a Agent // 要执行的 Agent
+ enableStreaming bool
+ store CheckPointStore // 用于中断恢复的状态存储
+}
+```
+
+**为什么需要 Runner?**
+
+虽然 Agent 提供了 `Run()` 方法,但直接调用会缺少很多运行时能力:
+
+1. **生命周期管理**:Runner 管理 Agent 的启动、恢复、中断等状态
+2. **Checkpoint 支持**:配合 `CheckPointStore` 实现中断恢复(后续章节涉及)
+3. **统一入口**:提供 `Run()` 和 `Query()` 等便捷方法
+4. **事件流封装**:将 Agent 的事件流转换为可消费的 `AsyncIterator[*AgentEvent]`
+
+**使用方式:**
+
+```go
+runner := adk.NewRunner(ctx, adk.RunnerConfig{
+ Agent: agent,
+ EnableStreaming: true,
+})
+
+// 方式 1:传入消息列表
+events := runner.Run(ctx, history)
+
+// 方式 2:便捷方法,传入单个查询字符串
+events := runner.Query(ctx, "你好")
+```
+
+### AgentEvent
+
+`AgentEvent` 是 Runner 返回的事件单元:
+
+```go
+type AgentEvent struct {
+ AgentName string
+ RunPath []RunStep
+
+ Output *AgentOutput // 输出内容
+ Action *AgentAction // 控制动作
+ Err error // 执行错误
+}
+```
+
+**主要字段:**
+
+- `event.Err`:执行错误
+- `event.Output.MessageOutput`:message 或 message stream(流式)
+- `event.Action`:中断/转移/退出等控制动作(后续章节用到)
+
+### AsyncIterator:事件流的消费方式
+
+`Runner.Run()` 返回的是 `*AsyncIterator[*AgentEvent]`,这是一个非阻塞的流式迭代器。
+
+**为什么用 AsyncIterator 而不是直接返回结果?**
+
+因为 Agent 的执行是**流式**的:模型逐 token 生成回复,Tool 调用穿插其中。如果等全部完成再返回,用户需要等待更长时间。`AsyncIterator` 让你可以实时消费每一个事件。
+
+**消费方式:**
+
+```go
+// events 是 *AsyncIterator[*AgentEvent],由 runner.Run() 返回
+events := runner.Run(ctx, history)
+
+for {
+ event, ok := events.Next() // 获取下一个事件,阻塞直到有事件或结束
+ if !ok {
+ break // 迭代器关闭,全部事件已消费
+ }
+ if event.Err != nil {
+ // 处理错误
+ }
+ if event.Output != nil && event.Output.MessageOutput != nil {
+ // 处理消息输出(可能是流式)
+ }
+}
+```
+
+**注意:**每次 `runner.Run()` 创建新的迭代器,消费一次后不可重复使用。
+
+## 多轮对话的实现
+
+本章实现的是简单的多轮对话:用户输入 → 模型回复 → 用户继续输入 → ...
+
+**实现方式:**
+
+没有 tools 时,`ChatModelAgent` 在一次 `Run()` 里只会完成一轮模型调用。多轮对话是通过调用侧维护 history 实现的:
+
+1. 用 `history []*schema.Message` 保存累计对话
+2. 每次用户输入:把 `UserMessage` 追加到 history
+3. 调用 `runner.Run(ctx, history)` 得到事件流,消费得到 assistant 文本
+4. 把本轮 assistant 文本追加回 history,进入下一轮
+
+**关键代码片段(**注意:这是简化后的代码片段,不能直接运行,完整代码请参考** [cmd/ch02/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch02/main.go)):
+
+```go
+history := make([]*schema.Message, 0, 16)
+
+for {
+ // 1. 读取用户输入
+ line := readUserInput()
+ if line == "" {
+ break
+ }
+
+ // 2. 追加用户消息到 history
+ history = append(history, schema.UserMessage(line))
+
+ // 3. 调用 Runner 执行 Agent
+ events := runner.Run(ctx, history)
+
+ // 4. 消费事件流,收集 assistant 回复
+ content := collectAssistantFromEvents(events)
+
+ // 5. 追加 assistant 消息到 history
+ history = append(history, schema.AssistantMessage(content, nil))
+}
+```
+
+**流程图:**
+
+```
+┌─────────────────────────────────────────┐
+│ 初始化 history = [] │
+└─────────────────────────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 用户输入 UserMessage │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 追加到 history │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ runner.Run(history) │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 消费事件流 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 追加 AssistantMessage│
+ └──────────────────────┘
+ ↓
+ (循环继续)
+```
+
+## 本章小结
+
+- **Agent 接口**:定义智能体的基本行为,核心是 `Run() -> AsyncIterator[*AgentEvent]`
+- **ChatModelAgent**:基于 ChatModel 实现的 Agent,提供统一的执行抽象
+- **Runner**:Agent 的执行入口,管理生命周期、checkpoint、事件流等运行时能力
+- **AgentEvent**:事件驱动的输出单元,支持流式响应和控制动作
+- **多轮对话**:通过调用侧维护 history 实现,每次 `Run()` 完成一轮对话
diff --git a/content/zh/docs/eino/quick_start/chapter_03_memory_and_session.md b/content/zh/docs/eino/quick_start/chapter_03_memory_and_session.md
new file mode 100644
index 00000000000..0eba8441743
--- /dev/null
+++ b/content/zh/docs/eino/quick_start/chapter_03_memory_and_session.md
@@ -0,0 +1,317 @@
+---
+Description: ""
+date: "2026-03-12"
+lastmod: ""
+tags: []
+title: 第三章:Memory 与 Session(持久化对话)
+weight: 3
+---
+
+本章目标:实现对话历史的持久化存储,支持跨进程恢复会话。
+
+> **⚠️ 重要说明:业务层概念 vs 框架概念**
+
+> 本章介绍的 **Memory、Session、Store 是业务层概念**,**不是 Eino 框架的核心组件**。
+
+>
+
+> 换句话说,Eino 框架只负责"如何处理消息",而"如何存储消息"完全由业务层决定。本章提供的实现只是一个简单的参考示例,你可以根据自己的业务需求选择完全不同的存储方案(数据库、Redis、云存储等)。
+
+## 代码位置
+
+- 入口代码:[cmd/ch03/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch03/main.go)
+- Memory 实现:[mem/store.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/mem/store.go)
+
+## 前置条件
+
+与第一章一致:需要配置一个可用的 ChatModel(OpenAI 或 Ark)。
+
+## 运行
+
+在 `examples/quickstart/chatwitheino` 目录下执行:
+
+```bash
+# 创建新会话
+go run ./cmd/ch03
+
+# 恢复已有会话
+go run ./cmd/ch03 --session
+```
+
+输出示例:
+
+```
+Created new session: 083d16da-6b13-4fe6-afb0-c45d8f490ce1
+Session title: New Session
+Enter your message (empty line to exit):
+you> 你好,我是张三
+[assistant] 你好张三!很高兴认识你...
+you> 我叫什么名字?
+[assistant] 你叫张三...
+
+Session saved: 083d16da-6b13-4fe6-afb0-c45d8f490ce1
+Resume with: go run ./cmd/ch03 --session 083d16da-6b13-4fe6-afb0-c45d8f490ce1
+```
+
+## 从内存到持久化:为什么需要 Memory
+
+第二章我们实现了多轮对话,但有一个问题:**对话历史只存在于内存中**。
+
+**内存存储的局限:**
+
+- 进程退出后,对话历史丢失
+- 无法跨设备、跨进程恢复会话
+- 无法实现会话管理(列表、删除、搜索等)
+
+**Memory 的定位:**
+
+- **Memory 是对话历史的持久化存储**:将对话保存到磁盘或数据库
+- **Memory 支持 Session 管理**:每个 Session 代表一次完整的对话
+- **Memory 与 Agent 解耦**:Agent 不关心存储细节,只关心消息列表
+
+**简单类比:**
+
+- **内存存储** = "草稿纸"(进程退出就没了)
+- **Memory** = "笔记本"(永久保存,随时翻阅)
+
+## 关键概念
+
+> **再次强调**:以下 Session、Store 等概念都是**业务层实现**,用于管理对话历史的存储。Eino 框架本身不提供这些组件,而是由业务层负责管理消息列表,然后将消息传递给 `adk.Runner` 进行处理。
+
+### Session(业务层概念)
+
+`Session` 代表一次完整的对话会话:
+
+```go
+type Session struct {
+ ID string
+ CreatedAt time.Time
+
+ messages []*schema.Message // 对话历史
+ // ...
+}
+```
+
+**核心方法:**
+
+- `Append(msg)`:追加消息到会话,并持久化
+- `GetMessages()`:获取所有消息
+- `Title()`:从第一条用户消息生成会话标题
+
+### Store(业务层概念)
+
+`Store` 管理多个 Session 的持久化存储:
+
+```go
+type Store struct {
+ dir string // 存储目录
+ cache map[string]*Session // 内存缓存
+}
+```
+
+**核心方法:**
+
+- `GetOrCreate(id)`:获取或创建 Session
+- `List()`:列出所有 Session
+- `Delete(id)`:删除 Session
+
+### JSONL 文件格式
+
+每个 Session 存储为一个 `.jsonl` 文件:
+
+```
+{"type":"session","id":"083d16da-...","created_at":"2026-03-11T10:00:00Z"}
+{"role":"user","content":"你好,我是谁?"}
+{"role":"assistant","content":"你好!我暂时不知道你是谁..."}
+{"role":"user","content":"我叫张三"}
+{"role":"assistant","content":"好的,张三,很高兴认识你!"}
+```
+
+**为什么用 JSONL?**
+
+- **简单**:每行一个 JSON 对象,易于读写
+- **可扩展**:可以追加新消息,无需重写整个文件
+- **可读性好**:可以用文本编辑器直接查看
+- **容错性强**:单行损坏不影响其他行
+
+## Memory 的实现(业务层示例)
+
+以下是一个简单的业务层实现示例,使用 JSONL 文件存储对话历史。这只是众多可能实现中的一种,你可以根据实际需求选择数据库、Redis 等其他存储方案。
+
+### 1. 创建 Store
+
+```go
+sessionDir := "./data/sessions"
+store, err := mem.NewStore(sessionDir)
+if err != nil {
+ log.Fatal(err)
+}
+```
+
+### 2. 获取或创建 Session
+
+```go
+sessionID := "083d16da-6b13-4fe6-afb0-c45d8f490ce1"
+session, err := store.GetOrCreate(sessionID)
+if err != nil {
+ log.Fatal(err)
+}
+```
+
+### 3. 追加用户消息
+
+```go
+userMsg := schema.UserMessage("你好")
+if err := session.Append(userMsg); err != nil {
+ log.Fatal(err)
+}
+```
+
+### 4. 获取历史并调用 Agent
+
+```go
+history := session.GetMessages()
+events := runner.Run(ctx, history)
+content := collectAssistantFromEvents(events)
+```
+
+### 5. 追加助手消息
+
+```go
+assistantMsg := schema.AssistantMessage(content, nil)
+if err := session.Append(assistantMsg); err != nil {
+ log.Fatal(err)
+}
+```
+
+**关键代码片段(**注意:这是简化后的代码片段,不能直接运行,完整代码请参考** [cmd/ch03/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch03/main.go)):
+
+```go
+// 创建或恢复 Session
+session, err := store.GetOrCreate(sessionID)
+if err != nil {
+ log.Fatal(err)
+}
+
+// 用户输入
+userMsg := schema.UserMessage(line)
+if err := session.Append(userMsg); err != nil {
+ log.Fatal(err)
+}
+
+// 调用 Agent
+history := session.GetMessages()
+events := runner.Run(ctx, history)
+content := collectAssistantFromEvents(events)
+
+// 保存助手回复
+assistantMsg := schema.AssistantMessage(content, nil)
+if err := session.Append(assistantMsg); err != nil {
+ log.Fatal(err)
+}
+```
+
+## Session 与 Agent 的关系:业务层与框架层的协作
+
+**关键理解:**
+
+- **Session 是业务层概念**:由业务代码实现和管理,负责存储和加载对话历史
+- **Agent(Runner)是框架层概念**:由 Eino 框架提供,负责处理消息并生成回复
+- **两者的交互点**:业务层通过 `session.GetMessages()` 获取消息列表,传递给 `runner.Run(ctx, history)` 进行处理
+
+**架构分层:**
+
+```
+┌─────────────────────────────────────────────────────────────┐
+│ 业务层(你的代码) │
+│ ┌─────────────┐ ┌──────────────┐ ┌───────────────┐ │
+│ │ Session │───→│ GetMessages() │───→│ runner.Run() │ │
+│ │ (存储) │ │ (消息列表) │ │ (框架调用) │ │
+│ └─────────────┘ └──────────────┘ └───────────────┘ │
+│ ↑ │ │
+│ │ ↓ │
+│ ┌─────────────┐ ┌───────────────┐ │
+│ │ Append() │←─────────────────────│ 助手回复 │ │
+│ │ (保存消息) │ └───────────────┘ │
+│ └─────────────┘ │
+└─────────────────────────────────────────────────────────────┘
+ │
+ ↓
+┌─────────────────────────────────────────────────────────────┐
+│ 框架层(Eino 框架) │
+│ ┌───────────────────────────────────────────────────────┐ │
+│ │ adk.Runner:接收消息列表,调用 ChatModel,返回回复 │ │
+│ └───────────────────────────────────────────────────────┘ │
+└─────────────────────────────────────────────────────────────┘
+```
+
+**流程图:**
+
+```
+┌─────────────────────────────────────────┐
+│ 用户输入 │
+└─────────────────────────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ session.Append() │
+ │ 保存用户消息 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ session.GetMessages()│
+ │ 获取完整历史 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ runner.Run(history) │
+ │ Agent 处理消息 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 收集助手回复 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ session.Append() │
+ │ 保存助手消息 │
+ └──────────────────────┘
+```
+
+## 本章小结
+
+**框架层 vs 业务层:**
+
+- **Eino 框架层**:提供 `adk.Runner`、`schema.Message` 等基础抽象,不关心消息如何存储
+- **业务层(本章实现)**:Memory/Session/Store 是业务层概念,用于管理对话历史的存储
+
+**业务层概念:**
+
+- **Memory**:对话历史的持久化存储,支持跨进程恢复
+- **Session**:一次完整的对话会话,包含 ID、创建时间、消息列表
+- **Store**:管理多个 Session 的存储,支持创建、获取、列表、删除
+- **JSONL 格式**:简单的文件格式,易于读写和扩展
+
+**业务层与框架层的交互:**
+
+- 业务层负责存储消息,通过 `session.GetMessages()` 获取消息列表
+- 将消息列表传递给框架层的 `runner.Run(ctx, history)` 进行处理
+- 收集框架层返回的回复,再由业务层保存到存储中
+
+> **💡 提示**:本章的实现只是众多存储方案中的一种简单示例。在实际项目中,你可以根据业务需求选择数据库、Redis、云存储等方案,甚至可以实现更复杂的功能如会话过期清理、搜索、分享等。
+
+## 扩展思考:业务层存储方案的选择
+
+本章提供的 JSONL 文件存储方案适合简单的单机应用。在实际业务中,你可能需要考虑其他存储方案:
+
+**其他存储实现:**
+
+- 数据库存储(MySQL、PostgreSQL、MongoDB)
+- Redis 存储(支持分布式)
+- 云存储(S3、OSS)
+
+**高级功能:**
+
+- 会话过期清理
+- 会话搜索
+- 会话导出/导入
+- 会话分享
diff --git a/content/zh/docs/eino/quick_start/chapter_04_tool_and_filesystem.md b/content/zh/docs/eino/quick_start/chapter_04_tool_and_filesystem.md
new file mode 100644
index 00000000000..9f0e38919c1
--- /dev/null
+++ b/content/zh/docs/eino/quick_start/chapter_04_tool_and_filesystem.md
@@ -0,0 +1,329 @@
+---
+Description: ""
+date: "2026-03-12"
+lastmod: ""
+tags: []
+title: 第四章:Tool 与文件系统访问
+weight: 4
+---
+
+本章目标:为 Agent 添加 Tool 能力,让 Agent 能够访问文件系统。
+
+## 为什么需要 Tool
+
+前三章我们实现的 Agent 只能对话,无法执行实际操作。
+
+**Agent 的局限:**
+
+- 只能生成文本回复
+- 无法访问外部资源(文件、API、数据库等)
+- 无法执行实际任务(计算、查询、修改等)
+
+**Tool 的定位:**
+
+- **Tool 是 Agent 的能力扩展**:让 Agent 能够执行具体操作
+- **Tool 封装了具体实现**:Agent 不关心 Tool 内部如何工作,只关心输入输出
+- **Tool 可组合**:一个 Agent 可以有多个 Tool,根据需要选择调用
+
+**简单类比:**
+
+- **Agent** = "智能助手"(能理解指令,但需要工具才能执行)
+- **Tool** = "工具箱"(文件操作、网络请求、数据库查询等)
+
+## 为什么需要文件系统能力
+
+本示例是 ChatWithDoc(与文档对话),目标是帮助用户学习 Eino 框架并编写 Eino 代码。那么,最好的文档是什么?
+
+**答案就是:Eino 仓库的代码本身。**
+
+- **Code**: 源代码展示了框架的真实实现
+- **Comment**: 代码注释提供了设计思路和使用说明
+- **Examples**: 示例代码演示了最佳实践
+
+通过文件系统访问能力,Agent 可以直接读取 Eino 源码、注释和示例,为用户提供最准确、最及时的技术支持。
+
+## 关键概念
+
+### Tool 接口
+
+`Tool` 是 Eino 中定义可执行能力的接口:
+
+```go
+// BaseTool 提供工具的元信息,ChatModel 使用这些信息决定是否以及如何调用工具
+type BaseTool interface {
+ Info(ctx context.Context) (*schema.ToolInfo, error)
+}
+
+// InvokableTool 是可以被 ToolsNode 执行的工具
+type InvokableTool interface {
+ BaseTool
+ // InvokableRun 执行工具,参数是 JSON 编码的字符串,返回字符串结果
+ InvokableRun(ctx context.Context, argumentsInJSON string, opts ...Option) (string, error)
+}
+
+// StreamableTool 是 InvokableTool 的流式变体
+type StreamableTool interface {
+ BaseTool
+ // StreamableRun 流式执行工具,返回 StreamReader
+ StreamableRun(ctx context.Context, argumentsInJSON string, opts ...Option) (*schema.StreamReader[string], error)
+}
+```
+
+**接口层次:**
+
+- `BaseTool`:基础接口,只提供元信息
+- `InvokableTool`:可执行工具(继承 BaseTool)
+- `StreamableTool`:流式工具(继承 BaseTool)
+
+### Backend 接口
+
+`Backend` 是 Eino 中用于文件系统操作的抽象接口:
+
+```go
+type Backend interface {
+ // 列出目录下的文件信息
+ LsInfo(ctx context.Context, req *LsInfoRequest) ([]FileInfo, error)
+
+ // 读取文件内容,支持按行偏移和限制
+ Read(ctx context.Context, req *ReadRequest) (*FileContent, error)
+
+ // 在文件中搜索匹配的内容
+ GrepRaw(ctx context.Context, req *GrepRequest) ([]GrepMatch, error)
+
+ // 根据 glob 模式匹配文件
+ GlobInfo(ctx context.Context, req *GlobInfoRequest) ([]FileInfo, error)
+
+ // 写入文件内容
+ Write(ctx context.Context, req *WriteRequest) error
+
+ // 编辑文件内容(字符串替换)
+ Edit(ctx context.Context, req *EditRequest) error
+}
+```
+
+### LocalBackend
+
+`LocalBackend` 是 Backend 的本地文件系统实现,直接访问操作系统的文件系统:
+
+```go
+import localbk "github.com/cloudwego/eino-ext/adk/backend/local"
+
+backend, err := localbk.NewBackend(ctx, &localbk.Config{})
+```
+
+**特点:**
+
+- 直接访问本地文件系统,使用 Go 标准库实现
+- 支持所有 Backend 接口方法
+- 支持执行 shell 命令(ExecuteStreaming)
+- 路径安全:要求使用绝对路径,防止目录遍历攻击
+- 零配置:开箱即用,无需额外设置
+
+## 实现:使用 DeepAgent
+
+本章使用 DeepAgent 预构建 Agent,它提供了 Backend 和 StreamingShell 的一级配置,可以方便地注册文件系统相关的工具。
+
+### 从 ChatModelAgent 到 DeepAgent:何时需要切换?
+
+前面章节一直使用 `ChatModelAgent`,它已经能处理多轮对话。但要访问文件系统,我们需要切换到 `DeepAgent`。
+
+**ChatModelAgent vs DeepAgent 对比:**
+
+
+| 能力 | ChatModelAgent | DeepAgent |
+| 多轮对话 | ✅ | ✅ |
+| 添加自定义 Tool | ✅ 手动注册每个 Tool | ✅ 手动注册或自动注册 |
+| 文件系统访问(Backend) | ❌ 需手动创建并注册所有文件工具 | ✅ 一级配置,自动注册 |
+| 命令执行(StreamingShell) | ❌ 需手动创建 | ✅ 一级配置,自动注册 |
+| 内置任务管理 | ❌ | ✅ write_todos 工具 |
+| 支持子 Agent | ❌ | ✅ |
+
+
+**选择建议:**
+
+- 纯对话场景(无外部访问)→ 用 `ChatModelAgent`
+- 需要访问文件系统或执行命令 → 用 `DeepAgent`
+
+### 为什么使用 DeepAgent?
+
+相比直接使用 ChatModelAgent,DeepAgent 的优势:
+
+1. **一级配置**: Backend 和 StreamingShell 是一级配置,直接传入即可
+2. **自动注册工具**: 配置 Backend 后自动注册文件系统工具,无需手动创建
+3. **内置任务管理**: 提供 `write_todos` 工具,支持任务规划和跟踪
+4. **支持子 Agent**: 可以配置专门的子 Agent 处理特定任务
+5. **更强大**: 集成了文件系统、命令执行等多种能力
+
+### 代码实现
+
+```go
+import (
+ localbk "github.com/cloudwego/eino-ext/adk/backend/local"
+ "github.com/cloudwego/eino/adk/prebuilt/deep"
+)
+
+// 创建 LocalBackend
+backend, err := localbk.NewBackend(ctx, &localbk.Config{})
+
+// 创建 DeepAgent,自动注册文件系统工具
+agent, err := deep.New(ctx, &deep.Config{
+ Name: "Ch04ToolAgent",
+ Description: "ChatWithDoc agent with filesystem access via LocalBackend.",
+ ChatModel: cm,
+ Instruction: instruction,
+ Backend: backend, // 提供文件系统操作能力
+ StreamingShell: backend, // 提供命令执行能力
+ MaxIteration: 50,
+})
+```
+
+### DeepAgent 自动注册的工具
+
+当配置了 `Backend` 和 `StreamingShell` 后,DeepAgent 会自动注册以下工具:
+
+- `read_file`: 读取文件内容
+- `write_file`: 写入文件内容
+- `edit_file`: 编辑文件内容
+- `glob`: 根据 glob 模式查找文件
+- `grep`: 在文件中搜索内容
+- `execute`: 执行 shell 命令
+
+## 代码位置
+
+- 入口代码:[cmd/ch04/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch04/main.go)
+
+## 前置条件
+
+与第一章一致:需要配置一个可用的 ChatModel(OpenAI 或 Ark)。
+
+本章还需要设置 `PROJECT_ROOT`(可选,见下方运行说明)。
+
+## 运行
+
+在 `examples/quickstart/chatwitheino` 目录下执行:
+
+```bash
+# 可选:设置 Eino 核心库的根目录路径
+# 未设置时,Agent 默认使用当前工作目录(即 chatwitheino 目录)作为根目录
+# 若要让 Agent 能检索完整的 Eino 代码库,建议指向 eino 核心库根目录
+export PROJECT_ROOT=/path/to/eino
+
+# 验证路径是否正确(应该能看到 adk、components、compose 等目录)
+ls $PROJECT_ROOT
+
+go run ./cmd/ch04
+```
+
+**PROJECT_ROOT 说明:**
+
+- **不设置时**:`PROJECT_ROOT` 默认为当前工作目录(`chatwitheino` 所在目录),Agent 只能访问本示例项目的文件。这对于快速试验已足够。
+- **设置后**:指向 Eino 核心库根目录,Agent 可以检索 Eino 框架的完整代码库(核心库、扩展库、示例库)。这是 ChatWithEino 的完整使用场景。
+
+**推荐的三仓库目录结构(如要完整体验):**
+
+```
+eino/ # PROJECT_ROOT(Eino 核心库)
+├── adk/
+├── components/
+├── compose/
+├── ext/ # eino-ext(扩展组件,如 OpenAI、Ark 等实现)
+├── examples/ # eino-examples(本仓库,本示例所在位置)
+│ └── quickstart/
+│ └── chatwitheino/
+└── ...
+```
+
+可以使用 `dev_setup.sh` 脚本自动设置上述目录结构:
+
+```bash
+# 在 eino 根目录运行,自动克隆扩展库和示例库到正确位置
+bash scripts/dev_setup.sh
+```
+
+输出示例:
+
+```
+you> 列出当前目录的文件
+[assistant] 我来帮你列出当前目录的文件...
+[tool call] glob(pattern: "*")
+[tool result] 找到 5 个文件:
+- main.go
+- go.mod
+- go.sum
+- README.md
+- cmd/
+
+you> 读取 main.go 文件的内容
+[assistant] 我来读取 main.go 文件...
+[tool call] read_file(file_path: "main.go")
+[tool result] 文件内容如下:
+...
+```
+
+**注意:** 如果在运行过程中遇到 Tool 报错导致 Agent 中断,请不要 panic,这是正常现象。Tool 报错是常见的情况,例如参数错误、文件不存在等。如何优雅地处理 Tool 错误,我们将在下一章详细介绍。
+
+## Tool 调用流程
+
+当 Agent 需要调用 Tool 时:
+
+```
+┌─────────────────────────────────────────┐
+│ 用户:列出当前目录的文件 │
+└─────────────────────────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ Agent 分析意图 │
+ │ 决定调用 glob 工具 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 生成 Tool Call │
+ │ {"pattern": "*"} │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 执行 Tool │
+ │ glob("*") │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 返回 Tool Result │
+ │ {"files": [...]} │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ Agent 生成回复 │
+ │ "找到 5 个文件..." │
+ └──────────────────────┘
+```
+
+## 本章小结
+
+- **Tool**:Agent 的能力扩展,让 Agent 能够执行具体操作
+- **Backend**:文件系统操作的抽象接口,提供统一的文件操作能力
+- **LocalBackend**:Backend 的本地文件系统实现,直接访问操作系统文件系统
+- **DeepAgent**:预构建的高级 Agent,提供 Backend 和 StreamingShell 的一级配置
+- **自动注册工具**:配置 Backend 后自动注册文件系统工具
+- **Tool 调用流程**:Agent 分析意图 → 生成 Tool Call → 执行 Tool → 返回结果 → 生成回复
+
+## 扩展思考
+
+**其他 Tool 类型:**
+
+- HTTP Tool:调用外部 API
+- Database Tool:查询数据库
+- Calculator Tool:执行计算
+- Code Executor Tool:运行代码
+
+**其他 Backend 实现:**
+
+- 可以基于 Backend 接口实现其他存储后端
+- 例如:云存储、数据库存储等
+- LocalBackend 已经提供了完整的文件系统操作能力
+
+**自定义 Tool 创建:**
+
+如果需要创建自定义 Tool,可以使用 `utils.InferTool` 从函数自动推断。详见:
+
+- [Tool 接口文档](https://github.com/cloudwego/eino/tree/main/components/tool)
+- [Tool 创建示例](https://github.com/cloudwego/eino-examples/tree/main/components/tool)
diff --git a/content/zh/docs/eino/quick_start/chapter_05_middleware.md b/content/zh/docs/eino/quick_start/chapter_05_middleware.md
new file mode 100644
index 00000000000..0bae0820e06
--- /dev/null
+++ b/content/zh/docs/eino/quick_start/chapter_05_middleware.md
@@ -0,0 +1,448 @@
+---
+Description: ""
+date: "2026-03-16"
+lastmod: ""
+tags: []
+title: 第五章:Middleware(中间件模式)
+weight: 5
+---
+
+本章目标:理解 Middleware 模式,实现 Tool 错误处理和 ChatModel 重试机制。
+
+## 为什么需要 Middleware
+
+第四章我们为 Agent 添加了 Tool 能力,让 Agent 能够访问文件系统。但在实际应用场景中,**Tool 报错或 ChatModel 报错是常见的现象**,例如:
+
+- **Tool 报错**:文件不存在、参数错误、权限不足等
+- **ChatModel 报错**:API 限流(429)、网络超时、服务不可用等
+
+### 问题一:Tool 错误会中断整个流程
+
+当 Tool 执行失败时,错误会直接传播到 Agent,导致整个对话中断:
+
+```
+[tool call] read_file(file_path: "nonexistent.txt")
+Error: open nonexistent.txt: no such file or directory
+// 对话中断,用户需要重新开始
+```
+
+### 问题二:模型调用可能因限流失败
+
+当模型 API 返回 429(Too Many Requests)错误时,整个对话也会中断:
+
+```
+Error: rate limit exceeded (429)
+// 对话中断
+```
+
+### 期望的行为
+
+这些报错信息往往**不希望直接终止 Agent 流程**,而是希望把报错信息给到模型,由模型自动纠错进行下一轮。例如:
+
+```
+[tool call] read_file(file_path: "nonexistent.txt")
+[tool result] [tool error] open nonexistent.txt: no such file or directory
+[assistant] 抱歉,文件不存在。让我先列出当前目录的文件...
+[tool call] glob(pattern: "*")
+```
+
+### Middleware 的定位
+
+**Middleware 模式**可以扩展 Tool 和 ChatModel 的行为,非常适合解决这个问题:
+
+- **Middleware 是 Agent 的拦截器**:在调用前后插入自定义逻辑
+- **Middleware 可处理错误**:将错误转换为模型可理解的格式
+- **Middleware 可实现重试**:自动重试失败的操作
+- **Middleware 可组合**:多个 Middleware 可以串联使用
+
+**简单类比:**
+
+- **Agent** = "业务逻辑"
+- **Middleware** = "AOP 切面"(日志、重试、错误处理等横切关注点)
+
+## 代码位置
+
+- 入口代码:[cmd/ch05/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch05/main.go)
+
+## 前置条件
+
+与第一章一致:需要配置一个可用的 ChatModel(OpenAI 或 Ark)。同时,需要与第四章一样设置 `PROJECT_ROOT`:
+
+```bash
+export PROJECT_ROOT=/path/to/eino # Eino 核心库根目录
+```
+
+## 运行
+
+在 `examples/quickstart/chatwitheino` 目录下执行:
+
+```bash
+# 设置项目根目录
+export PROJECT_ROOT=/path/to/your/project
+
+go run ./cmd/ch05
+```
+
+输出示例:
+
+```
+you> 列出当前目录的文件
+[assistant] 我来帮你列出文件...
+[tool call] list_files(directory: ".")
+
+you> 读取一个不存在的文件
+[assistant] 尝试读取文件...
+[tool call] read_file(file_path: "nonexistent.txt")
+[tool result] [tool error] open nonexistent.txt: no such file or directory
+[assistant] 抱歉,文件不存在...
+```
+
+## 关键概念
+
+### Middleware 接口
+
+`ChatModelAgentMiddleware` 是 Agent 的中间件接口:
+
+```go
+type ChatModelAgentMiddleware interface {
+ // BeforeAgent is called before each agent run, allowing modification of
+ // the agent's instruction and tools configuration.
+ BeforeAgent(ctx context.Context, runCtx *ChatModelAgentContext) (context.Context, *ChatModelAgentContext, error)
+
+ // BeforeModelRewriteState is called before each model invocation.
+ // The returned state is persisted to the agent's internal state and passed to the model.
+ BeforeModelRewriteState(ctx context.Context, state *ChatModelAgentState, mc *ModelContext) (context.Context, *ChatModelAgentState, error)
+
+ // AfterModelRewriteState is called after each model invocation.
+ // The input state includes the model's response as the last message.
+ AfterModelRewriteState(ctx context.Context, state *ChatModelAgentState, mc *ModelContext) (context.Context, *ChatModelAgentState, error)
+
+ // WrapInvokableToolCall wraps a tool's synchronous execution with custom behavior.
+ // This method is only called for tools that implement InvokableTool.
+ WrapInvokableToolCall(ctx context.Context, endpoint InvokableToolCallEndpoint, tCtx *ToolContext) (InvokableToolCallEndpoint, error)
+
+ // WrapStreamableToolCall wraps a tool's streaming execution with custom behavior.
+ // This method is only called for tools that implement StreamableTool.
+ WrapStreamableToolCall(ctx context.Context, endpoint StreamableToolCallEndpoint, tCtx *ToolContext) (StreamableToolCallEndpoint, error)
+
+ // WrapEnhancedInvokableToolCall wraps an enhanced tool's synchronous execution.
+ // This method is only called for tools that implement EnhancedInvokableTool.
+ WrapEnhancedInvokableToolCall(ctx context.Context, endpoint EnhancedInvokableToolCallEndpoint, tCtx *ToolContext) (EnhancedInvokableToolCallEndpoint, error)
+
+ // WrapEnhancedStreamableToolCall wraps an enhanced tool's streaming execution.
+ // This method is only called for tools that implement EnhancedStreamableTool.
+ WrapEnhancedStreamableToolCall(ctx context.Context, endpoint EnhancedStreamableToolCallEndpoint, tCtx *ToolContext) (EnhancedStreamableToolCallEndpoint, error)
+
+ // WrapModel wraps a chat model with custom behavior.
+ // This method is called at request time when the model is about to be invoked.
+ WrapModel(ctx context.Context, m model.BaseChatModel, mc *ModelContext) (model.BaseChatModel, error)
+}
+```
+
+**设计理念:**
+
+- **装饰器模式**:每个 Middleware 包装原始调用,可以修改输入、输出或错误
+- **洋葱模型**:请求从外向内穿过 Middleware,响应从内向外返回
+- **可组合**:多个 Middleware 按顺序执行
+
+### Middleware 执行顺序
+
+`Handlers`(即 Middlewares)按**数组正序**包装,形成洋葱模型:
+
+```go
+Handlers: []adk.ChatModelAgentMiddleware{
+ &middlewareA{}, // 最外层:最先 Wrap,最先拦截请求,但 WrapModel 最后生效
+ &middlewareB{}, // 中间层
+ &middlewareC{}, // 最内层:最后 Wrap
+}
+```
+
+**对于 Tool 调用的执行顺序:**
+
+```
+请求 → A.Wrap → B.Wrap → C.Wrap → 实际 Tool 执行 → C返回 → B返回 → A返回 → 响应
+```
+
+**实用建议:** 将 `safeToolMiddleware`(错误捕获)放在最内层(数组末尾),确保其他 Middleware 抛出的中断错误能正确向外传播。
+
+### SafeToolMiddleware
+
+`SafeToolMiddleware` 将 Tool 错误转换为字符串,让模型能够理解并处理:
+
+```go
+type safeToolMiddleware struct {
+ *adk.BaseChatModelAgentMiddleware
+}
+
+func (m *safeToolMiddleware) WrapInvokableToolCall(
+ _ context.Context,
+ endpoint adk.InvokableToolCallEndpoint,
+ _ *adk.ToolContext,
+) (adk.InvokableToolCallEndpoint, error) {
+ return func(ctx context.Context, args string, opts ...tool.Option) (string, error) {
+ result, err := endpoint(ctx, args, opts...)
+ if err != nil {
+ // 将错误转换为字符串,而不是返回错误
+ return fmt.Sprintf("[tool error] %v", err), nil
+ }
+ return result, nil
+ }, nil
+}
+```
+
+**效果:**
+
+```
+[tool call] read_file(file_path: "nonexistent.txt")
+[tool result] [tool error] open nonexistent.txt: no such file or directory
+[assistant] 抱歉,文件不存在,请检查文件路径...
+// 对话继续,模型可以根据错误信息调整策略
+```
+
+### ModelRetryConfig
+
+`ModelRetryConfig` 配置 ChatModel 的自动重试:
+
+```go
+type ModelRetryConfig struct {
+ MaxRetries int // 最大重试次数
+ IsRetryAble func(ctx context.Context, err error) bool // 判断是否可重试
+}
+```
+
+**使用方式(以 DeepAgent 为例):**
+
+```go
+agent, err := deep.New(ctx, &deep.Config{
+ // ...
+ ModelRetryConfig: &adk.ModelRetryConfig{
+ MaxRetries: 5,
+ IsRetryAble: func(_ context.Context, err error) bool {
+ // 429 限流错误可重试
+ return strings.Contains(err.Error(), "429") ||
+ strings.Contains(err.Error(), "Too Many Requests") ||
+ strings.Contains(err.Error(), "qpm limit")
+ },
+ },
+})
+```
+
+**重试策略:**
+
+- 指数退避:每次重试间隔递增
+- 可配置条件:通过 `IsRetryAble` 判断哪些错误可重试
+- 自动恢复:无需用户干预
+
+## Middleware 的实现
+
+### 1. 实现 SafeToolMiddleware
+
+```go
+type safeToolMiddleware struct {
+ *adk.BaseChatModelAgentMiddleware
+}
+
+func (m *safeToolMiddleware) WrapInvokableToolCall(
+ _ context.Context,
+ endpoint adk.InvokableToolCallEndpoint,
+ _ *adk.ToolContext,
+) (adk.InvokableToolCallEndpoint, error) {
+ return func(ctx context.Context, args string, opts ...tool.Option) (string, error) {
+ result, err := endpoint(ctx, args, opts...)
+ if err != nil {
+ // 中断错误不转换,需要继续传播
+ if _, ok := compose.IsInterruptRerunError(err); ok {
+ return "", err
+ }
+ // 其他错误转换为字符串
+ return fmt.Sprintf("[tool error] %v", err), nil
+ }
+ return result, nil
+ }, nil
+}
+```
+
+### 2. 实现流式 Tool 错误处理
+
+```go
+func (m *safeToolMiddleware) WrapStreamableToolCall(
+ _ context.Context,
+ endpoint adk.StreamableToolCallEndpoint,
+ _ *adk.ToolContext,
+) (adk.StreamableToolCallEndpoint, error) {
+ return func(ctx context.Context, args string, opts ...tool.Option) (*schema.StreamReader[string], error) {
+ sr, err := endpoint(ctx, args, opts...)
+ if err != nil {
+ if _, ok := compose.IsInterruptRerunError(err); ok {
+ return nil, err
+ }
+ // 返回包含错误信息的单帧流
+ return singleChunkReader(fmt.Sprintf("[tool error] %v", err)), nil
+ }
+ // 包装流,捕获流中的错误
+ return safeWrapReader(sr), nil
+ }, nil
+}
+```
+
+### 3. 配置 Agent 使用 Middleware
+
+本章继续使用第四章引入的 `DeepAgent`,在其 `Handlers` 字段中注册 Middleware:
+
+```go
+agent, err := deep.New(ctx, &deep.Config{
+ Name: "Ch05MiddlewareAgent",
+ Description: "ChatWithDoc agent with safe tool middleware and retry.",
+ ChatModel: cm,
+ Instruction: agentInstruction,
+ Backend: backend,
+ StreamingShell: backend,
+ MaxIteration: 50,
+ Handlers: []adk.ChatModelAgentMiddleware{
+ &safeToolMiddleware{}, // 将 Tool 错误转换为字符串
+ },
+ ModelRetryConfig: &adk.ModelRetryConfig{
+ MaxRetries: 5,
+ IsRetryAble: func(_ context.Context, err error) bool {
+ return strings.Contains(err.Error(), "429") ||
+ strings.Contains(err.Error(), "Too Many Requests")
+ },
+ },
+})
+```
+
+**注意**:`Handlers` 字段(在配置中)和 "Middleware"(在文档中讨论的概念)是同一回事——`Handlers` 是配置字段名,而 `ChatModelAgentMiddleware` 是接口名。
+
+```
+**关键代码片段(**注意:这是简化后的代码片段,不能直接运行,完整代码请参考** [cmd/ch05/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch05/main.go)):
+
+```go
+// SafeToolMiddleware 捕获 Tool 错误并转换为字符串
+type safeToolMiddleware struct {
+ *adk.BaseChatModelAgentMiddleware
+}
+
+func (m *safeToolMiddleware) WrapInvokableToolCall(
+ _ context.Context,
+ endpoint adk.InvokableToolCallEndpoint,
+ _ *adk.ToolContext,
+) (adk.InvokableToolCallEndpoint, error) {
+ return func(ctx context.Context, args string, opts ...tool.Option) (string, error) {
+ result, err := endpoint(ctx, args, opts...)
+ if err != nil {
+ if _, ok := compose.IsInterruptRerunError(err); ok {
+ return "", err
+ }
+ return fmt.Sprintf("[tool error] %v", err), nil
+ }
+ return result, nil
+ }, nil
+}
+
+// 配置 DeepAgent(与第四章一样,新增 Handlers 和 ModelRetryConfig)
+agent, _ := deep.New(ctx, &deep.Config{
+ ChatModel: cm,
+ Backend: backend,
+ StreamingShell: backend,
+ MaxIteration: 50,
+ Handlers: []adk.ChatModelAgentMiddleware{
+ &safeToolMiddleware{},
+ },
+ ModelRetryConfig: &adk.ModelRetryConfig{
+ MaxRetries: 5,
+ IsRetryAble: func(_ context.Context, err error) bool {
+ return strings.Contains(err.Error(), "429")
+ },
+ },
+})
+```
+
+## Middleware 执行流程
+
+```
+┌─────────────────────────────────────────┐
+│ 用户:读取不存在的文件 │
+└─────────────────────────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ Agent 分析意图 │
+ │ 决定调用 read_file │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ SafeToolMiddleware │
+ │ 拦截 Tool 调用 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 执行 read_file │
+ │ 返回错误 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ SafeToolMiddleware │
+ │ 将错误转换为字符串 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 返回 Tool Result │
+ │ "[tool error] ..." │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ Agent 生成回复 │
+ │ "抱歉,文件不存在..." │
+ └──────────────────────┘
+```
+
+## 本章小结
+
+- **Middleware**:Agent 的拦截器,可以在调用前后插入自定义逻辑
+- **SafeToolMiddleware**:将 Tool 错误转换为字符串,让模型能够理解并处理
+- **ModelRetryConfig**:配置 ChatModel 的自动重试,处理限流等临时错误
+- **装饰器模式**:Middleware 包装原始调用,可以修改输入、输出或错误
+- **洋葱模型**:请求从外向内穿过 Middleware,响应从内向外返回
+
+## 扩展思考
+
+**Eino 内置 Middleware:**
+
+
+| Middleware | 功能说明 |
+| reduction | 工具输出缩减,当工具返回内容过长时自动截断并卸载到文件系统,防止上下文溢出 |
+| summarization | 对话历史自动摘要,当 token 数量超过阈值时自动生成摘要压缩历史 |
+| skill | 技能加载中间件,让 Agent 能够动态加载和执行预定义的技能 |
+
+
+**Middleware 链示例:**
+
+```go
+import (
+ "github.com/cloudwego/eino/adk/middlewares/reduction"
+ "github.com/cloudwego/eino/adk/middlewares/summarization"
+ "github.com/cloudwego/eino/adk/middlewares/skill"
+)
+
+// 创建 reduction middleware:管理工具输出长度
+reductionMW, _ := reduction.New(ctx, &reduction.Config{
+ Backend: filesystemBackend, // 存储后端
+ MaxLengthForTrunc: 50000, // 单次工具输出最大长度
+ MaxTokensForClear: 30000, // 触发清理的 token 阈值
+})
+
+// 创建 summarization middleware:自动压缩对话历史
+summarizationMW, _ := summarization.New(ctx, &summarization.Config{
+ Model: chatModel, // 用于生成摘要的模型
+ Trigger: &summarization.TriggerCondition{
+ ContextTokens: 190000, // 触发摘要的 token 阈值
+ },
+})
+
+// 组合多个 middleware(概念示例,使用 DeepAgent 时将 adk.NewChatModelAgent 替换为 deep.New)
+agent, _ := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
+ Handlers: []adk.ChatModelAgentMiddleware{ // 注意:配置字段名为 Handlers,概念上与 Middlewares 等价
+ summarizationMW, // 最外层:对话历史摘要
+ reductionMW, // 中间层:工具输出缩减
+ },
+})
+```
diff --git a/content/zh/docs/eino/quick_start/chapter_06_callback_and_trace.md b/content/zh/docs/eino/quick_start/chapter_06_callback_and_trace.md
new file mode 100644
index 00000000000..0ff7dfadc2d
--- /dev/null
+++ b/content/zh/docs/eino/quick_start/chapter_06_callback_and_trace.md
@@ -0,0 +1,367 @@
+---
+Description: ""
+date: "2026-03-12"
+lastmod: ""
+tags: []
+title: 第六章:Callback 与 Trace(可观测性)
+weight: 6
+---
+
+本章目标:理解 Callback 机制,集成 CozeLoop 实现链路追踪和可观测性。
+
+## 代码位置
+
+- 入口代码:[cmd/ch06/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch06/main.go)
+
+## 前置条件
+
+与第一章一致:需要配置一个可用的 ChatModel(OpenAI 或 Ark)。同时,需要与第四章一样设置 `PROJECT_ROOT`:
+
+```bash
+export PROJECT_ROOT=/path/to/eino # Eino 核心库根目录(不设置则默认使用当前目录)
+```
+
+可选:配置 CozeLoop 实现链路追踪:
+
+```bash
+export COZELOOP_WORKSPACE_ID=your_workspace_id
+export COZELOOP_API_TOKEN=your_token
+```
+
+## 运行
+
+在 `examples/quickstart/chatwitheino` 目录下执行:
+
+```bash
+# 设置项目根目录
+export PROJECT_ROOT=/path/to/your/project
+
+# 可选:配置 CozeLoop
+export COZELOOP_WORKSPACE_ID=your_workspace_id
+export COZELOOP_API_TOKEN=your_token
+
+go run ./cmd/ch06
+```
+
+输出示例:
+
+```
+[trace] starting session: 083d16da-6b13-4fe6-afb0-c45d8f490ce1
+you> 你好
+[trace] chat_model_generate: model=gpt-4.1-mini tokens=150
+[trace] tool_call: name=list_files duration=23ms
+[assistant] 你好!有什么我可以帮助你的吗?
+```
+
+## 从黑盒到白盒:为什么需要 Callback
+
+前几章我们实现的 Agent 是一个"黑盒":输入问题,输出答案,但中间发生了什么我们并不清楚。
+
+**黑盒的问题:**
+
+- 不知道模型调用了多少次
+- 不知道 Tool 执行了多长时间
+- 不知道 Token 消耗了多少
+- 出问题时难以定位原因
+
+**Callback 的定位:**
+
+- **Callback 是 Eino 的旁路机制**:从 component 到 compose(下文详谈)到 adk,一以贯之
+- **Callback 在固定点位触发**:组件生命周期的 5 个关键时机
+- **Callback 可抽取实时信息**:输入、输出、错误、流式数据等
+- **Callback 用途广泛**:观测、日志、指标、追踪、调试、审计等
+
+**简单类比:**
+
+- **Agent** = "业务逻辑"(主路)
+- **Callback** = "旁路钩子"(在固定点位抽取信息)
+
+## 关键概念
+
+### Handler 接口
+
+`Handler` 是 Eino 中定义回调处理器的核心接口:
+
+```go
+type Handler interface {
+ // 非流式输入(组件开始处理前)
+ OnStart(ctx context.Context, info *RunInfo, input CallbackInput) context.Context
+
+ // 非流式输出(组件成功返回后)
+ OnEnd(ctx context.Context, info *RunInfo, output CallbackOutput) context.Context
+
+ // 错误(组件返回错误时)
+ OnError(ctx context.Context, info *RunInfo, err error) context.Context
+
+ // 流式输入(组件接收流式输入时)
+ OnStartWithStreamInput(ctx context.Context, info *RunInfo,
+ input *schema.StreamReader[CallbackInput]) context.Context
+
+ // 流式输出(组件返回流式输出时)
+ OnEndWithStreamOutput(ctx context.Context, info *RunInfo,
+ output *schema.StreamReader[CallbackOutput]) context.Context
+}
+```
+
+**设计理念:**
+
+- **旁路机制**:不干扰主流程,在固定点位抽取信息
+- **全流程覆盖**:从 component 到 compose 到 adk,所有组件都支持
+- **状态传递**:同一 Handler 的 OnStart→OnEnd 可通过 context 传递状态
+- **性能优化**:实现 `TimingChecker` 接口可跳过不需要的时机
+
+**RunInfo 结构:**
+
+```go
+type RunInfo struct {
+ Name string // 业务名称(节点名或用户指定)
+ Type string // 实现类型(如 "OpenAI")
+ Component string // 组件类型(如 "ChatModel")
+}
+```
+
+**重要提示:**
+
+- 流式回调必须关闭 StreamReader,否则会导致 goroutine 泄漏
+- 不要修改 Input/Output,它们被所有下游共享
+- RunInfo 可能为 nil,使用前需要检查
+
+### CozeLoop
+
+CozeLoop 是字节跳动开源的 AI 应用可观测性平台,提供了:
+
+- **链路追踪**:完整的调用链路可视化
+- **指标监控**:延迟、Token 消耗、错误率等
+- **日志聚合**:集中管理所有日志
+- **调试支持**:在线查看和调试
+
+**集成方式:**
+
+```go
+import (
+ clc "github.com/cloudwego/eino-ext/callbacks/cozeloop"
+ "github.com/cloudwego/eino/callbacks"
+ "github.com/coze-dev/cozeloop-go"
+)
+
+// 创建 CozeLoop 客户端
+client, err := cozeloop.NewClient(
+ cozeloop.WithAPIToken(apiToken),
+ cozeloop.WithWorkspaceID(workspaceID),
+)
+
+// 注册为全局 Callback
+callbacks.AppendGlobalHandlers(clc.NewLoopHandler(client))
+```
+
+### Callback 的触发时机
+
+Callback 在组件生命周期的 5 个关键时机触发。下表中 `Timing*` 是 Eino 内部常量名(用于 `TimingChecker` 接口),对应的 Handler 接口方法是右侧所示:
+
+
+| 时机常量 | 对应 Handler 方法 | 触发点 | 输入/输出 |
+TimingOnStart | OnStart | 组件开始处理前 | CallbackInput |
+TimingOnEnd | OnEnd | 组件成功返回后 | CallbackOutput |
+TimingOnError | OnError | 组件返回错误时 | error |
+TimingOnStartWithStreamInput | OnStartWithStreamInput | 组件接收流式输入时 | StreamReader[CallbackInput] |
+TimingOnEndWithStreamOutput | OnEndWithStreamOutput | 组件返回流式输出时 | StreamReader[CallbackOutput] |
+
+
+**示例:ChatModel 调用流程**
+
+```
+┌─────────────────────────────────────────┐
+│ ChatModel.Generate(ctx, messages) │
+└─────────────────────────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ OnStart │ ← 输入: CallbackInput (messages)
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 模型处理 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ OnEnd │ ← 输出: CallbackOutput (response)
+ └──────────────────────┘
+```
+
+**示例:流式输出流程**
+
+```
+┌─────────────────────────────────────────┐
+│ ChatModel.Stream(ctx, messages) │
+└─────────────────────────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ OnStart │ ← 输入: CallbackInput (messages)
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 模型处理(流式) │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ OnEndWithStreamOutput │ ← 输出: StreamReader[CallbackOutput]
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 逐个 chunk 返回 │
+ └──────────────────────┘
+```
+
+**注意:**
+
+- 流式错误(stream 中途出错)不会触发 OnError,而是在 StreamReader 中返回
+- 同一 Handler 的 OnStart→OnEnd 可通过 context 传递状态
+- 不同 Handler 之间没有执行顺序保证
+
+## Callback 的实现
+
+### 1. 实现自定义 Callback Handler
+
+完整实现 `Handler` 接口需要实现所有 5 个方法,较为繁琐。Eino 提供了 `callbacks.HandlerHelper` 帮助类来简化实现:
+
+```go
+import "github.com/cloudwego/eino/callbacks"
+
+// 使用 NewHandlerHelper 注册感兴趣的回调
+handler := callbacks.NewHandlerHelper().
+ OnStart(func(ctx context.Context, info *callbacks.RunInfo, input callbacks.CallbackInput) context.Context {
+ log.Printf("[trace] %s/%s start", info.Component, info.Name)
+ return ctx
+ }).
+ OnEnd(func(ctx context.Context, info *callbacks.RunInfo, output callbacks.CallbackOutput) context.Context {
+ log.Printf("[trace] %s/%s end", info.Component, info.Name)
+ return ctx
+ }).
+ OnError(func(ctx context.Context, info *callbacks.RunInfo, err error) context.Context {
+ log.Printf("[trace] %s/%s error: %v", info.Component, info.Name, err)
+ return ctx
+ }).
+ Handler()
+
+// 注册为全局 Callback
+callbacks.AppendGlobalHandlers(handler)
+```
+
+**注意**:`RunInfo` 可能为 `nil`(如顶层调用没有 RunInfo),使用前请检查。
+
+### 2. 集成 CozeLoop
+
+```go
+func setupCozeLoop(ctx context.Context) (*cozeloop.Client, error) {
+ apiToken := os.Getenv("COZELOOP_API_TOKEN")
+ workspaceID := os.Getenv("COZELOOP_WORKSPACE_ID")
+
+ if apiToken == "" || workspaceID == "" {
+ return nil, nil // 未配置则跳过
+ }
+
+ client, err := cozeloop.NewClient(
+ cozeloop.WithAPIToken(apiToken),
+ cozeloop.WithWorkspaceID(workspaceID),
+ )
+ if err != nil {
+ return nil, err
+ }
+
+ // 注册为全局 Callback
+ callbacks.AppendGlobalHandlers(clc.NewLoopHandler(client))
+
+ return client, nil
+}
+```
+
+### 3. 在 main 中使用
+
+```go
+func main() {
+ ctx := context.Background()
+
+ // 设置 CozeLoop(可选)
+ client, err := setupCozeLoop(ctx)
+ if err != nil {
+ log.Printf("cozeloop setup failed: %v", err)
+ }
+ if client != nil {
+ defer func() {
+ time.Sleep(5 * time.Second) // 等待数据上报
+ client.Close(ctx)
+ }()
+ }
+
+ // 创建 Agent 并运行...
+}
+```
+
+**关键代码片段(**注意:这是简化后的代码片段,不能直接运行,完整代码请参考** [cmd/ch06/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch06/main.go)):
+
+```go
+// 设置 CozeLoop 追踪
+cozeloopApiToken := os.Getenv("COZELOOP_API_TOKEN")
+cozeloopWorkspaceID := os.Getenv("COZELOOP_WORKSPACE_ID")
+if cozeloopApiToken != "" && cozeloopWorkspaceID != "" {
+ client, err := cozeloop.NewClient(
+ cozeloop.WithAPIToken(cozeloopApiToken),
+ cozeloop.WithWorkspaceID(cozeloopWorkspaceID),
+ )
+ if err != nil {
+ log.Fatalf("cozeloop.NewClient failed: %v", err)
+ }
+ defer func() {
+ time.Sleep(5 * time.Second)
+ client.Close(ctx)
+ }()
+ callbacks.AppendGlobalHandlers(clc.NewLoopHandler(client))
+}
+```
+
+## 可观测性的价值
+
+### 1. 性能分析
+
+通过 Callback 收集的数据,可以分析:
+
+- 模型调用延迟分布
+- Tool 执行时间排行
+- Token 消耗趋势
+
+### 2. 错误追踪
+
+当 Agent 出现问题时:
+
+- 查看完整的调用链路
+- 定位是哪个环节出错
+- 分析错误原因
+
+### 3. 成本优化
+
+通过 Token 消耗数据:
+
+- 识别高消耗的对话
+- 优化 Prompt 减少 Token
+- 选择更经济的模型
+
+## 本章小结
+
+- **Callback**:Eino 的观测钩子,在关键节点触发回调
+- **CozeLoop**:字节跳动的 AI 应用可观测性平台
+- **全局注册**:通过 `callbacks.AppendGlobalHandlers` 注册全局 Callback
+- **非侵入式**:业务代码不需要修改,Callback 自动触发
+- **可观测性价值**:性能分析、错误追踪、成本优化
+
+## 扩展思考
+
+**其他 Callback 实现:**
+
+- OpenTelemetry Callback:对接标准可观测性协议
+- 自定义日志 Callback:记录到本地文件
+- 指标 Callback:对接 Prometheus 等监控系统
+
+**高级用法:**
+
+- 在 Callback 中实现采样(只记录部分请求)
+- 在 Callback 中实现限流(根据 Token 消耗)
+- 在 Callback 中实现告警(错误率过高时通知)
diff --git a/content/zh/docs/eino/quick_start/chapter_07_interrupt_resume.md b/content/zh/docs/eino/quick_start/chapter_07_interrupt_resume.md
new file mode 100644
index 00000000000..87b6bd4b55d
--- /dev/null
+++ b/content/zh/docs/eino/quick_start/chapter_07_interrupt_resume.md
@@ -0,0 +1,355 @@
+---
+Description: ""
+date: "2026-03-16"
+lastmod: ""
+tags: []
+title: 第七章:Interrupt/Resume(中断与恢复)
+weight: 7
+---
+
+本章目标:理解 Interrupt/Resume 机制,实现 Tool 审批流程,让用户在敏感操作前进行确认。
+
+## 代码位置
+
+- 入口代码:[cmd/ch07/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch07/main.go)
+
+## 前置条件
+
+与第一章一致:需要配置一个可用的 ChatModel(OpenAI 或 Ark)。同时,需要与第四章一样设置 `PROJECT_ROOT`:
+
+```bash
+export PROJECT_ROOT=/path/to/eino # Eino 核心库根目录(不设置则默认使用当前目录)
+```
+
+## 运行
+
+在 `examples/quickstart/chatwitheino` 目录下执行:
+
+```bash
+# 设置项目根目录
+export PROJECT_ROOT=/path/to/your/project
+
+go run ./cmd/ch07
+```
+
+输出示例:
+
+```
+you> 请执行命令 echo hello
+
+⚠️ Approval Required ⚠️
+Tool: execute
+Arguments: {"command":"echo hello"}
+
+Approve this action? (y/n): y
+[tool result] hello
+
+hello
+```
+
+## 从自动执行到人工审批:为什么需要 Interrupt
+
+前几章我们实现的 Agent 会自动执行所有 Tool 调用,但在某些场景下这是危险的:
+
+**自动执行的风险:**
+
+- 删除文件:误删重要数据
+- 发送邮件:发送错误内容
+- 执行命令:执行危险操作
+- 修改配置:破坏系统设置
+
+**Interrupt 的定位:**
+
+- **Interrupt 是 Agent 的暂停机制**:在关键操作前暂停,等待用户确认
+- **Interrupt 可携带信息**:向用户展示即将执行的操作
+- **Interrupt 可恢复**:用户确认后继续执行,拒绝后返回错误
+
+**简单类比:**
+
+- **自动执行** = "自动驾驶"(完全信任系统)
+- **Interrupt** = "人工接管"(关键决策由人来做)
+
+## 关键概念
+
+### Interrupt 机制
+
+`Interrupt` 是 Eino 中实现人机协作的核心机制。
+
+**核心思想:在执行关键操作前暂停,等待用户确认后继续。**
+
+一个需要审批的 Tool 的执行被分成**两个阶段**:
+
+1. **第一次调用(触发中断)**:Tool 保存当前参数,然后返回一个中断信号。Runner 暂停执行,向调用侧返回 Interrupt 事件。
+2. **用户审批后恢复(Resume)**:Runner 重新调用 Tool,此时 Tool 检测到"已中断过",直接读取用户的审批结果并执行(或拒绝)。
+
+**简化版伪代码:**
+
+```
+func myTool(ctx, args):
+ if 第一次调用:
+ 保存 args
+ return 中断信号 // Runner 暂停,展示审批提示
+ else: // Resume 后的第二次调用
+ if 用户批准:
+ return 执行操作(保存的 args)
+ else:
+ return "操作被用户拒绝"
+```
+
+**完整代码及关键字段说明:**
+
+```go
+// 在 Tool 中触发中断
+func myTool(ctx context.Context, args string) (string, error) {
+ // wasInterrupted: 是否是 Resume 后的第二次调用(第一次为 false,Resume 后为 true)
+ // storedArgs: 第一次调用时通过 StatefulInterrupt 保存的参数,Resume 后可取回
+ wasInterrupted, _, storedArgs := tool.GetInterruptState[string](ctx)
+
+ if !wasInterrupted {
+ // 第一次调用:触发中断,同时保存 args 供 Resume 后使用
+ return "", tool.StatefulInterrupt(ctx, &ApprovalInfo{
+ ToolName: "my_tool",
+ ArgumentsInJSON: args,
+ }, args) // 第三个参数是要保存的状态(Resume 后通过 storedArgs 取回)
+ }
+
+ // Resume 后的第二次调用:读取用户审批结果
+ // isTarget: 本次 Resume 是否针对当前 Tool(一次 Resume 只针对一个 Tool)
+ // hasData: Resume 时是否携带了审批结果数据
+ // data: 用户传入的审批结果
+ isTarget, hasData, data := tool.GetResumeContext[*ApprovalResult](ctx)
+ if isTarget && hasData {
+ if data.Approved {
+ return doSomething(storedArgs) // 使用保存的参数执行实际操作
+ }
+ return "Operation rejected by user", nil
+ }
+
+ // 其他情况(isTarget=false 意味着本次 Resume 目标不是当前 Tool):重新中断
+ return "", tool.StatefulInterrupt(ctx, &ApprovalInfo{
+ ToolName: "my_tool",
+ ArgumentsInJSON: storedArgs,
+ }, storedArgs)
+}
+```
+
+### ApprovalMiddleware
+
+`ApprovalMiddleware` 是一个通用的审批中间件,可以拦截特定 Tool 的调用:
+
+```go
+type approvalMiddleware struct {
+ *adk.BaseChatModelAgentMiddleware
+}
+
+func (m *approvalMiddleware) WrapInvokableToolCall(
+ _ context.Context,
+ endpoint adk.InvokableToolCallEndpoint,
+ tCtx *adk.ToolContext,
+) (adk.InvokableToolCallEndpoint, error) {
+ // 只拦截需要审批的 Tool
+ if tCtx.Name != "execute" {
+ return endpoint, nil
+ }
+
+ return func(ctx context.Context, args string, opts ...tool.Option) (string, error) {
+ wasInterrupted, _, storedArgs := tool.GetInterruptState[string](ctx)
+
+ if !wasInterrupted {
+ return "", tool.StatefulInterrupt(ctx, &commontool.ApprovalInfo{
+ ToolName: tCtx.Name,
+ ArgumentsInJSON: args,
+ }, args)
+ }
+
+ isTarget, hasData, data := tool.GetResumeContext[*commontool.ApprovalResult](ctx)
+ if isTarget && hasData {
+ if data.Approved {
+ return endpoint(ctx, storedArgs, opts...)
+ }
+ if data.DisapproveReason != nil {
+ return fmt.Sprintf("tool '%s' disapproved: %s", tCtx.Name, *data.DisapproveReason), nil
+ }
+ return fmt.Sprintf("tool '%s' disapproved", tCtx.Name), nil
+ }
+
+ // 重新中断
+ return "", tool.StatefulInterrupt(ctx, &commontool.ApprovalInfo{
+ ToolName: tCtx.Name,
+ ArgumentsInJSON: storedArgs,
+ }, storedArgs)
+ }, nil
+}
+
+func (m *approvalMiddleware) WrapStreamableToolCall(
+ _ context.Context,
+ endpoint adk.StreamableToolCallEndpoint,
+ tCtx *adk.ToolContext,
+) (adk.StreamableToolCallEndpoint, error) {
+ // 如果 agent 配置了 StreamingShell,则 execute 会走流式调用,需要实现该方法才能拦截到
+ if tCtx.Name != "execute" {
+ return endpoint, nil
+ }
+ return func(ctx context.Context, args string, opts ...tool.Option) (*schema.StreamReader[string], error) {
+ wasInterrupted, _, storedArgs := tool.GetInterruptState[string](ctx)
+ if !wasInterrupted {
+ return nil, tool.StatefulInterrupt(ctx, &commontool.ApprovalInfo{
+ ToolName: tCtx.Name,
+ ArgumentsInJSON: args,
+ }, args)
+ }
+
+ isTarget, hasData, data := tool.GetResumeContext[*commontool.ApprovalResult](ctx)
+ if isTarget && hasData {
+ if data.Approved {
+ return endpoint(ctx, storedArgs, opts...)
+ }
+ if data.DisapproveReason != nil {
+ return singleChunkReader(fmt.Sprintf("tool '%s' disapproved: %s", tCtx.Name, *data.DisapproveReason)), nil
+ }
+ return singleChunkReader(fmt.Sprintf("tool '%s' disapproved", tCtx.Name)), nil
+ }
+
+ isTarget, _, _ = tool.GetResumeContext[any](ctx)
+ if !isTarget {
+ return nil, tool.StatefulInterrupt(ctx, &commontool.ApprovalInfo{
+ ToolName: tCtx.Name,
+ ArgumentsInJSON: storedArgs,
+ }, storedArgs)
+ }
+
+ return endpoint(ctx, storedArgs, opts...)
+ }, nil
+}
+```
+
+### CheckPointStore
+
+`CheckPointStore` 是实现中断恢复的关键组件:
+
+```go
+type CheckPointStore interface {
+ // 保存检查点
+ Put(ctx context.Context, key string, checkpoint *Checkpoint) error
+
+ // 获取检查点
+ Get(ctx context.Context, key string) (*Checkpoint, error)
+}
+```
+
+**为什么需要 CheckPointStore?**
+
+- 中断时保存状态:Tool 参数、执行位置等
+- 恢复时加载状态:从中断点继续执行
+- 支持跨进程恢复:进程重启后仍可恢复
+
+## Interrupt/Resume 的实现
+
+### 1. 配置 Runner 使用 CheckPointStore
+
+```go
+runner := adk.NewRunner(ctx, adk.RunnerConfig{
+ Agent: agent,
+ EnableStreaming: true,
+ CheckPointStore: adkstore.NewInMemoryStore(), // 内存存储
+})
+```
+
+### 2. 配置 Agent 使用 ApprovalMiddleware
+
+```go
+agent, err := deep.New(ctx, &deep.Config{
+ // ... 其他配置
+ Handlers: []adk.ChatModelAgentMiddleware{
+ &approvalMiddleware{}, // 添加审批中间件
+ &safeToolMiddleware{}, // 将 Tool 错误转换为字符串(中断类错误会继续向上抛出)
+ },
+})
+```
+
+### 3. 处理中断事件
+
+```go
+checkPointID := sessionID
+
+events := runner.Run(ctx, history, adk.WithCheckPointID(checkPointID))
+content, interruptInfo, err := printAndCollectAssistantFromEvents(events)
+if err != nil {
+ return err
+}
+
+if interruptInfo != nil {
+ // 注意:建议使用同一个 stdin reader 同时读取「用户输入」与「审批 y/n」
+ // 避免审批输入被当成下一轮 you> 的消息
+ content, err = handleInterrupt(ctx, runner, checkPointID, interruptInfo, reader)
+ if err != nil {
+ return err
+ }
+}
+
+_ = session.Append(schema.AssistantMessage(content, nil))
+```
+
+## Interrupt/Resume 执行流程
+
+```
+┌─────────────────────────────────────────┐
+│ 用户:执行命令 echo hello │
+└─────────────────────────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ Agent 分析意图 │
+ │ 决定调用 execute │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ ApprovalMiddleware │
+ │ 拦截 Tool 调用 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 触发 Interrupt │
+ │ 保存状态到 Store │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 返回 Interrupt 事件 │
+ │ 等待用户审批 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 用户输入 y/n │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ runner.ResumeWith... │
+ │ 恢复执行 │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 执行 execute │
+ │ 或返回拒绝信息 │
+ └──────────────────────┘
+```
+
+## 本章小结
+
+- **Interrupt**:Agent 的暂停机制,在关键操作前暂停等待确认
+- **Resume**:恢复执行,用户确认后继续或拒绝后返回错误
+- **ApprovalMiddleware**:通用审批中间件,拦截特定 Tool 调用
+- **CheckPointStore**:保存中断状态,支持跨进程恢复
+- **人机协作**:关键决策由人来确认,提高安全性
+
+## 扩展思考
+
+**其他 Interrupt 场景:**
+
+- 多选项审批:用户选择多个选项之一
+- 参数补全:用户提供缺失的参数
+- 条件分支:用户决定执行路径
+
+**审批策略:**
+
+- 白名单:只审批敏感操作
+- 黑名单:审批所有操作,除了安全的
+- 动态规则:根据参数内容决定是否审批
diff --git a/content/zh/docs/eino/quick_start/chapter_08_graph_tool.md b/content/zh/docs/eino/quick_start/chapter_08_graph_tool.md
new file mode 100644
index 00000000000..c7562e9d062
--- /dev/null
+++ b/content/zh/docs/eino/quick_start/chapter_08_graph_tool.md
@@ -0,0 +1,313 @@
+---
+Description: ""
+date: "2026-03-12"
+lastmod: ""
+tags: []
+title: 第八章:Graph Tool(复杂工作流)
+weight: 8
+---
+
+本章目标:理解 Graph Tool 的概念,实现大文件的并行 chunk 召回,引入 compose 包构建复杂工作流。
+
+## 代码位置
+
+- 入口代码:[cmd/ch08/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch08/main.go)
+- RAG 实现:[rag/rag.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/rag/rag.go)
+
+## 前置条件
+
+与第一章一致:需要配置一个可用的 ChatModel(OpenAI 或 Ark)。
+
+## 运行
+
+在 `examples/quickstart/chatwitheino` 目录下执行:
+
+```bash
+# 设置项目根目录
+export PROJECT_ROOT=/path/to/your/project
+
+go run ./cmd/ch08
+```
+
+输出示例:
+
+```
+you> 请帮我分析 RFC6455 文档中关于 WebSocket 握手的部分
+[assistant] 我来帮你分析文档...
+[tool call] answer_from_document(file_path: "rfc6455.txt", question: "WebSocket 握手过程")
+[tool result] 找到 3 个相关片段,正在生成答案...
+[assistant] 根据 RFC6455 文档,WebSocket 握手过程如下...
+```
+
+## 从简单 Tool 到 Graph Tool:为什么需要复杂工作流
+
+第四章我们创建了简单的 Tool,每个 Tool 执行单一任务。但实际场景中,很多任务需要多个步骤协同完成。
+
+**简单 Tool 的局限:**
+
+- 单一职责:每个 Tool 只做一件事
+- 无法并行:多个独立任务无法同时执行
+- 难以复用:复杂逻辑难以拆分和组合
+
+**重要说明:本章只是展示 compose/graph/workflow 能力的一角。**
+
+从更大的视角看,Eino 的 `compose` 包提供了非常通用、确定性的编排能力:你可以把任何需要"确定性业务流程"的系统,用 `compose` 的 Graph/Chain/Workflow 组织成可执行的流水线,并且它能够**原生编排 Eino 的所有 component**(如 ChatModel、Prompt、Tools、Retriever、Embedding、Indexer 等),同时具备完整的 **callback** 体系,以及 **interrupt/resume + checkpoint** 支持。
+
+**Graph Tool 的定位:**
+
+- **Graph Tool 是 compose 工作流的 Tool 化封装**:把 `compose.Graph / compose.Chain / compose.Workflow` 这类可编译的编排产物,包装成一个 Agent 可调用的 Tool
+- **支持并行/分支/组合**:由 compose 提供(并行、分支、字段映射、子图等),Graph Tool 只是把它们暴露为 Tool 入口
+- **支持状态管理与持久化**:节点间传递数据、以及通过 checkpoint 保存/恢复运行状态
+- **可中断恢复**:既支持工作流内部的中断(节点里触发 interrupt),也支持工具层面的中断包装(嵌套 interrupt 场景)
+
+**简单类比:**
+
+- **简单 Tool** = "单步操作"(读取文件)
+- **Graph Tool** = "流水线"(读取 → 分块 → 评分 → 筛选 → 生成答案)
+
+## 关键概念
+
+### compose.Workflow
+
+`compose.Workflow` 是 Eino 中构建工作流的核心组件:
+
+```go
+wf := compose.NewWorkflow[Input, Output]()
+
+// 添加节点
+wf.AddLambdaNode("load", loadFunc).AddInput(compose.START)
+wf.AddLambdaNode("chunk", chunkFunc).AddInput("load")
+wf.AddLambdaNode("score", scoreFunc).AddInput("chunk")
+wf.AddLambdaNode("answer", answerFunc).AddInput("score")
+
+// 连接到结束节点
+wf.End().AddInput("answer")
+```
+
+**核心概念:**
+
+- **Node**:工作流中的处理单元
+- **Edge**:节点间的数据流向
+- **START**:工作流的入口
+- **END**:工作流的出口
+
+### BatchNode
+
+`BatchNode` 用于并行处理多个任务:
+
+```go
+scorer := batch.NewBatchNode(&batch.NodeConfig[Task, Result]{
+ Name: "ChunkScorer",
+ InnerTask: scoreOneChunk, // 单个任务的处理函数
+ MaxConcurrency: 5, // 最大并发数
+})
+```
+
+**工作原理:**
+
+1. 接收任务列表作为输入
+2. 并行执行每个任务(受 MaxConcurrency 限制)
+3. 收集所有结果返回
+
+### FieldMapping
+
+`FieldMapping` 用于跨节点传递数据:
+
+```go
+wf.AddLambdaNode("answer", answerFunc).
+ AddInputWithOptions("filter", // 从 filter 节点获取数据
+ []*compose.FieldMapping{compose.ToField("TopK")},
+ compose.WithNoDirectDependency()).
+ AddInputWithOptions(compose.START, // 从 START 节点获取数据
+ []*compose.FieldMapping{compose.MapFields("Question", "Question")},
+ compose.WithNoDirectDependency())
+```
+
+**为什么需要 FieldMapping?**
+
+- 非相邻节点间传递数据
+- 多个数据源合并到同一节点
+- 数据字段重命名
+
+## Graph Tool 的实现
+
+### 1. 定义输入输出结构
+
+```go
+type Input struct {
+ FilePath string `json:"file_path" jsonschema:"description=Absolute path to the document"`
+ Question string `json:"question" jsonschema:"description=The question to answer"`
+}
+
+type Output struct {
+ Answer string `json:"answer"`
+ Sources []string `json:"sources"`
+}
+```
+
+### 2. 构建工作流
+
+```go
+func buildWorkflow(cm model.BaseChatModel) *compose.Workflow[Input, Output] {
+ wf := compose.NewWorkflow[Input, Output]()
+
+ // load: 读取文件
+ wf.AddLambdaNode("load", compose.InvokableLambda(
+ func(ctx context.Context, in Input) ([]*schema.Document, error) {
+ data, err := os.ReadFile(in.FilePath)
+ if err != nil {
+ return nil, err
+ }
+ return []*schema.Document{{Content: string(data)}}, nil
+ },
+ )).AddInput(compose.START)
+
+ // chunk: 分块
+ wf.AddLambdaNode("chunk", compose.InvokableLambda(
+ func(ctx context.Context, docs []*schema.Document) ([]*schema.Document, error) {
+ var out []*schema.Document
+ for _, d := range docs {
+ out = append(out, splitIntoChunks(d.Content, 800)...)
+ }
+ return out, nil
+ },
+ )).AddInput("load")
+
+ // score: 并行评分
+ scorer := batch.NewBatchNode(&batch.NodeConfig[scoreTask, scoredChunk]{
+ Name: "ChunkScorer",
+ InnerTask: newScoreWorkflow(cm),
+ MaxConcurrency: 5,
+ })
+
+ wf.AddLambdaNode("score", compose.InvokableLambda(
+ func(ctx context.Context, in scoreIn) ([]scoredChunk, error) {
+ tasks := make([]scoreTask, len(in.Chunks))
+ for i, c := range in.Chunks {
+ tasks[i] = scoreTask{Text: c.Content, Question: in.Question}
+ }
+ return scorer.Invoke(ctx, tasks)
+ },
+ )).
+ AddInputWithOptions("chunk", []*compose.FieldMapping{compose.ToField("Chunks")}, compose.WithNoDirectDependency()).
+ AddInputWithOptions(compose.START, []*compose.FieldMapping{compose.MapFields("Question", "Question")}, compose.WithNoDirectDependency())
+
+ // filter: 筛选 top-k
+ wf.AddLambdaNode("filter", compose.InvokableLambda(
+ func(ctx context.Context, scored []scoredChunk) ([]scoredChunk, error) {
+ sort.Slice(scored, func(i, j int) bool {
+ return scored[i].Score > scored[j].Score
+ })
+ // 返回 top-3
+ if len(scored) > 3 {
+ scored = scored[:3]
+ }
+ return scored, nil
+ },
+ )).AddInput("score")
+
+ // answer: 生成答案
+ wf.AddLambdaNode("answer", compose.InvokableLambda(
+ func(ctx context.Context, in synthIn) (Output, error) {
+ return synthesize(ctx, cm, in)
+ },
+ )).
+ AddInputWithOptions("filter", []*compose.FieldMapping{compose.ToField("TopK")}, compose.WithNoDirectDependency()).
+ AddInputWithOptions(compose.START, []*compose.FieldMapping{compose.MapFields("Question", "Question")}, compose.WithNoDirectDependency())
+
+ wf.End().AddInput("answer")
+
+ return wf
+}
+```
+
+### 3. 封装为 Tool
+
+```go
+func BuildTool(ctx context.Context, cm model.BaseChatModel) (tool.BaseTool, error) {
+ wf := buildWorkflow(cm)
+ return graphtool.NewInvokableGraphTool[Input, Output](
+ wf,
+ "answer_from_document",
+ "Search a large document for relevant content and synthesize an answer.",
+ )
+}
+```
+
+**关键代码片段(**注意:这是简化后的代码片段,不能直接运行,完整代码请参考** [rag/rag.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/rag/rag.go)):
+
+```go
+// 构建工作流
+wf := compose.NewWorkflow[Input, Output]()
+
+// 添加节点
+wf.AddLambdaNode("load", loadFunc).AddInput(compose.START)
+wf.AddLambdaNode("chunk", chunkFunc).AddInput("load")
+wf.AddLambdaNode("score", scoreFunc).
+ AddInputWithOptions("chunk", []*compose.FieldMapping{compose.ToField("Chunks")}, compose.WithNoDirectDependency()).
+ AddInputWithOptions(compose.START, []*compose.FieldMapping{compose.MapFields("Question", "Question")}, compose.WithNoDirectDependency())
+
+// 封装为 Tool
+return graphtool.NewInvokableGraphTool[Input, Output](wf, "answer_from_document", "...")
+```
+
+## Graph Tool 执行流程
+
+```
+┌─────────────────────────────────────────┐
+│ 输入:file_path, question │
+└─────────────────────────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ load: 读取文件 │
+ │ 输出: []*Document │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ chunk: 分块 │
+ │ 输出: []*Document │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ score: 并行评分 │
+ │ (MaxConcurrency=5) │
+ │ 输出: []scoredChunk │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ filter: 筛选 top-k │
+ │ 输出: []scoredChunk │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ answer: 生成答案 │
+ │ 输出: Output │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 返回结果 │
+ │ {answer, sources} │
+ └──────────────────────┘
+```
+
+## 本章小结
+
+- **Graph Tool**:将复杂工作流封装为 Tool,支持多步骤协同
+- **compose.Workflow**:构建工作流的核心组件
+- **BatchNode**:并行处理多个任务
+- **FieldMapping**:跨节点传递数据
+- **可中断恢复**:Graph Tool 支持 Checkpoint 机制
+
+## 扩展思考
+
+**其他 Graph Tool 应用:**
+
+- 多文档 RAG:并行处理多个文档
+- 多模型协作:不同模型处理不同任务
+- 复杂决策树:根据条件选择不同分支
+
+**性能优化:**
+
+- 调整 MaxConcurrency 控制并发
+- 使用缓存避免重复计算
+- 流式输出提升用户体验
diff --git a/content/zh/docs/eino/quick_start/chapter_09_a2ui_protocol.md b/content/zh/docs/eino/quick_start/chapter_09_a2ui_protocol.md
new file mode 100644
index 00000000000..4aa55ea6ab2
--- /dev/null
+++ b/content/zh/docs/eino/quick_start/chapter_09_a2ui_protocol.md
@@ -0,0 +1,252 @@
+---
+Description: ""
+date: "2026-03-16"
+lastmod: ""
+tags: []
+title: 第九章:A2UI 协议(流式 UI 组件)
+weight: 10
+---
+
+本章目标:实现 A2UI 协议,将 Agent 的输出渲染为流式 UI 组件。
+
+## 重要说明:A2UI 的边界
+
+A2UI 并不属于 Eino 框架本身的范畴,它是一个业务层的 UI 协议/渲染方案。本章把 A2UI 集成进前面章节逐步构建出来的 Agent,是为了提供一个端到端、可落地的完整示例:从模型调用、工具调用、工作流编排,到最终把结果以更友好的 UI 方式呈现出来。
+
+在真实业务场景中,你完全可以根据产品形态选择不同的 UI 形式,例如:
+
+- Web / App:自定义组件、表格、卡片、图表等
+- IM/办公套件:消息卡片、交互式表单
+- 命令行:纯文本或 TUI(终端 UI)
+
+Eino 更关注“可组合的智能执行与编排能力”,至于“如何呈现给用户”,属于业务层可以自由扩展的一环。
+
+## 代码位置
+
+- 入口代码:[main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/main.go)
+- Agent 构建:[agent.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/agent.go)
+- 服务端路由:[server/server.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/server/server.go)
+- A2UI 子集实现:[a2ui/types.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/a2ui/types.go)
+- A2UI 事件流转换:[a2ui/streamer.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/a2ui/streamer.go)
+- 前端页面:[static/index.html](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/static/index.html)
+
+## 前置条件
+
+与第一章一致:需要配置一个可用的 ChatModel(OpenAI 或 Ark)
+
+## 运行
+
+在 `quickstart/chatwitheino` 目录下执行:
+
+```bash
+go run .
+```
+
+输出示例:
+
+```
+starting server on http://localhost:8080
+```
+
+### (可选)启用 ch09 的 skills 能力
+
+最终 Web 版使用的 Agent 构建逻辑与 Chapter 9 对齐:当 `EINO_EXT_SKILLS_DIR` 指向一个合法 skills 目录时,会自动注册 `skill` 中间件,模型就能按需调用 `skill` 工具加载 `eino-guide` / `eino-component` / `eino-compose` / `eino-agent`。
+
+```bash
+go run ./scripts/sync_eino_ext_skills.go -src /path/to/eino-ext -dest ./skills/eino-ext -clean
+EINO_EXT_SKILLS_DIR="$(pwd)/skills/eino-ext" go run .
+```
+
+## 从文本到 UI:为什么需要 A2UI
+
+前八章我们实现的 Agent 只输出文本,但现代 AI 应用需要更丰富的交互。
+
+**纯文本输出的局限:**
+
+- 无法展示结构化数据(表格、列表、卡片等)
+- 无法实时更新(进度条、状态变化等)
+- 无法嵌入交互元素(按钮、表单、链接等)
+- 无法支持多媒体(图片、视频、音频等)
+
+**A2UI 的定位:**
+
+- **A2UI 是 Agent 到 UI 的协议**:定义了 Agent 输出如何映射到 UI 组件
+- **A2UI 支持流式渲染**:组件可以实时更新,无需等待完整响应
+- **A2UI 是声明式的**:Agent 只需声明"显示什么",UI 负责渲染
+
+**简单类比:**
+
+- **纯文本输出** = "终端命令行"(只能显示文本)
+- **A2UI** = "Web 应用"(可以显示任何 UI 组件)
+
+## 关键概念
+
+### A2UI v0.8 子集(本示例的边界)
+
+本 quickstart 并没有实现一个“完整的 A2UI 标准库”,而是实现了一个 **A2UI v0.8 的子集**:目标是把 Agent 的事件流,以稳定、可增量渲染的 UI 组件树方式推给浏览器。
+
+当前实现的 A2UI 消息类型与组件类型,以 [a2ui/types.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/a2ui/types.go) 为准。
+
+### A2UI 消息:BeginRendering / SurfaceUpdate / DataModelUpdate / InterruptRequest
+
+每一行 SSE(`data: {...}`)承载一个 A2UI Message,Message 是一个“信封结构”,每次只会出现一个字段:
+
+**关键代码片段(注意:这是简化后的代码片段,不能直接运行,完整代码请参考 a2ui/types.go):**
+
+```go
+type Message struct {
+ BeginRendering *BeginRenderingMsg
+ SurfaceUpdate *SurfaceUpdateMsg
+ DataModelUpdate *DataModelUpdateMsg
+ DeleteSurface *DeleteSurfaceMsg
+ InterruptRequest *InterruptRequestMsg
+}
+```
+
+其中:
+
+- `BeginRendering`:告诉前端“开始渲染一个 surface(会话)”,并指定根节点 ID
+- `SurfaceUpdate`:新增/更新一批组件(组件是一个树,用 `id` 互相引用)
+- `DataModelUpdate`:更新 data bindings(用于把流式文本增量更新到某个 Text 组件)
+- `InterruptRequest`:当 Agent 触发 interrupt(例如审批)时,通知前端展示批准/拒绝入口
+
+### A2UI 组件:Text / Column / Card / Row
+
+本示例 UI 组件只实现了 4 种(见 [a2ui/types.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/a2ui/types.go)):
+
+- `Text`:文本渲染(支持 `usageHint` 区分 caption/body/title);当 `dataKey` 存在时,文本来自 `DataModelUpdate`
+- `Column` / `Row`:布局(children 是组件 ID 列表)
+- `Card`:卡片容器(children 是组件 ID 列表)
+
+## A2UI 的实现:把 AgentEvent 转成 A2UI SSE
+
+最终 Web 版的核心链路是:
+
+- 后端运行 Agent,得到 `*adk.AsyncIterator[*adk.AgentEvent]`
+- 把事件流转换为 A2UI JSONL/SSE 流输出给浏览器(见 [a2ui/streamer.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/a2ui/streamer.go))
+- 前端解析 SSE 的 `data:` 行并渲染组件树(见 [static/index.html](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/static/index.html))
+
+### 服务端路由(高层)
+
+与 A2UI 相关的关键接口(见 [server/server.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/server/server.go)):
+
+- `GET /`:返回前端页面 `static/index.html`
+- `POST /sessions/:id/chat`:返回 SSE 流(A2UI messages),把 Agent 运行结果边跑边渲染到 UI
+- `GET /sessions/:id/render`:返回 JSONL(A2UI messages),用于“选中会话时回放历史”
+- `POST /sessions/:id/approve`:处理 interrupt 的批准/拒绝并继续返回 SSE 流
+
+### 事件流转换(高层)
+
+服务端把 `Runner.Run(...)` 的事件流交给 `a2ui.StreamToWriter(...)`,后者负责:
+
+- 对 user/assistant/tool 的输出做拆分
+- 把 tool call / tool result 渲染成 “chip 卡片”
+- 把 assistant 的流式 token 做成 `DataModelUpdate`,实现“边生成边渲染”
+- 遇到 interrupt 时发送 `InterruptRequest`,并暂停等待人类批准
+
+## 前端集成:fetch + SSE(不是 WebSocket)
+
+- 前端通过 `fetch('/sessions/:id/chat')` 发起请求,然后从 `res.body` 读取流式字节,按行切分并解析 `data: {...}` 的 JSON(见 [static/index.html](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/static/index.html))。
+
+**关键代码片段(注意:这是简化后的代码片段,不能直接运行,完整代码请参考 static/index.html):**
+
+```javascript
+const res = await fetch(`/sessions/${id}/chat`, {
+ method: 'POST',
+ headers: {'Content-Type': 'application/json'},
+ body: JSON.stringify({message}),
+});
+
+const reader = res.body.getReader();
+const decoder = new TextDecoder();
+let buffer = '';
+while (true) {
+ const {done, value} = await reader.read();
+ if (done) break;
+ buffer += decoder.decode(value, {stream: true});
+ const lines = buffer.split('\n');
+ buffer = lines.pop();
+ for (const line of lines) {
+ const trimmed = line.trim();
+ if (trimmed.startsWith('data:')) {
+ const jsonStr = trimmed.slice(5).trimStart();
+ processA2UIMessage(JSON.parse(jsonStr));
+ }
+ }
+}
+```
+
+## A2UI 流式渲染流程(概览)
+
+```
+┌─────────────────────────────────────────┐
+│ 用户:分析这个文件 │
+└─────────────────────────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ Agent 开始处理 │
+ │ A2UI: AddText │
+ │ "正在分析..." │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 调用 Tool │
+ │ A2UI: AddProgress │
+ │ 进度: 0% │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ Tool 执行中 │
+ │ A2UI: UpdateProgress│
+ │ 进度: 50% │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ Tool 完成 │
+ │ A2UI: tool result │
+ └──────────────────────┘
+ ↓
+ ┌──────────────────────┐
+ │ 显示结果 │
+ │ A2UI: DataModelUpdate│
+ │ (流式更新 assistant)│
+ └──────────────────────┘
+```
+
+## 本章小结
+
+- **A2UI**:Agent 到 UI 的协议,定义了 Agent 输出如何映射到 UI 组件
+- **子集实现**:本示例只实现了 Text/Column/Card/Row 与 data binding
+- **流式输出**:后端以 SSE 推送 A2UI JSONL,前端增量渲染组件树
+- **事件到 UI**:把 `AgentEvent` 转为 `tool call / tool result / assistant stream` 的可视化输出
+
+## 系列收尾:这个 Quickstart Agent 的完整愿景
+
+到本章为止,我们用一个可以实际运行的 Agent 串起了 Eino 的核心能力。你可以把它理解为一个可扩展的“端到端 Agent 应用骨架”:
+
+- 运行时:Runner 驱动执行,支持流式输出与事件模型
+- 工具层:Filesystem / Shell 等 Tool 能力接入,工具错误可被安全处理
+- 中间件:可插拔的 middleware/handler,用于错误处理、重试、审批等横切能力
+- 可观测:callbacks/trace 能力把关键链路打通,便于调试与线上观测
+- 人机协作:interrupt/resume + checkpoint 支持审批、补参、分支选择等交互式流程
+- 确定性编排:compose(graph/chain/workflow)把复杂业务流程组织为可维护、可复用的执行图
+- 业务交付:像 A2UI 这样的 UI 集成,属于业务层自由选择的一环,用来把 Agent 能力以合适的产品形态呈现给用户
+
+你可以在这个骨架上逐步替换/扩展任意环节:模型、工具、存储、工作流、前端渲染协议,而不需要推倒重来。
+
+## 扩展思考
+
+**其他组件类型:**
+
+- 图表组件(折线图、柱状图、饼图)
+- 地图组件
+- 时间线组件
+- 树形组件
+- 标签页组件
+
+**高级功能:**
+
+- 组件交互(点击、拖拽、输入)
+- 条件渲染
+- 组件动画
+- 响应式布局
diff --git a/content/zh/docs/eino/quick_start/chapter_09_skill_console.md b/content/zh/docs/eino/quick_start/chapter_09_skill_console.md
new file mode 100644
index 00000000000..00f92c5f447
--- /dev/null
+++ b/content/zh/docs/eino/quick_start/chapter_09_skill_console.md
@@ -0,0 +1,142 @@
+---
+Description: ""
+date: "2026-03-16"
+lastmod: ""
+tags: []
+title: 第九章:Skill(Console)
+weight: 9
+---
+
+本章目标:在第八章(RAG + Interrupt/Resume + Checkpoint)基础上,引入 `skill` 中间件,让 Agent 可以发现并加载一组可复用的技能文档(`SKILL.md`),并在需要时通过工具调用使用它们。
+
+## 代码位置
+
+- 入口代码:[cmd/ch09/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/cmd/ch09/main.go)
+- 同步脚本:[scripts/sync_eino_ext_skills.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chatwitheino/scripts/sync_eino_ext_skills.go)
+
+## 前置条件
+
+- 与第一章一致:需要配置一个可用的 ChatModel(OpenAI 或 Ark)
+- 准备好 `eino-ext` PR 提供的 skills(`eino-guide` / `eino-component` / `eino-compose` / `eino-agent`)
+
+为什么是这四个?
+
+ChatWithEino 的定位是“帮用户学习 Eino 框架、并尝试用 AI 辅助写 Eino 代码”。这四个 skills 正好覆盖了这个目标所需的关键知识面:
+
+- `eino-guide`:学习入口与导航(从哪里开始、怎么快速跑起来)
+- `eino-component`:Component 接口与各类实现参考(Model/Embedding/Retriever/Tool/Callback 等)
+- `eino-compose`:编排与确定性工作流参考(Graph/Chain/Workflow 等)
+- `eino-agent`:ADK/Agent 相关参考(Agent、Runner、Middleware、Filesystem、Human-in-the-loop 等)
+
+skills 的来源可以是:
+
+- `eino-ext` 仓库本地路径(脚本会自动读取 `/skills/...`)
+- 或你已安装 skills 的目录(目录下能看到上述四个子目录)
+
+## 从 Graph Tool 到 Skill:为什么需要“技能文档”
+
+第八章解决的是“复杂工作流如何做成一个可调用的 Tool”(Graph Tool)。但你在构建一个面向框架学习/开发辅助的 Agent 时,还会遇到另一类问题:**如何把一组稳定、可复用的知识与指令注入到 Agent 里,并让它在运行时按需加载?**
+
+这就是 Skill 的定位:
+
+- **Tool** 更像“动作/能力”:读文件、跑 workflow、调用外部系统
+- **Skill** 更像“可复用的知识/指令包”:用一组 markdown(`SKILL.md` + `reference/*.md`)描述“如何做某类事”
+
+简单类比:
+
+- **Tool** = “能做什么”(函数/接口)
+- **Skill** = “怎么做”(可复用的说明书/操作手册)
+
+## 运行
+
+在 `quickstart/chatwitheino` 目录下执行:
+
+### 1) 同步 eino-ext skills 到本地目录
+
+为了让 `skill` 中间件可以“发现”这些 skills,需要把它们放到一个统一目录下,并满足扫描约定:
+
+- `EINO_EXT_SKILLS_DIR//SKILL.md`
+
+同步命令(推荐):
+
+```bash
+go run ./scripts/sync_eino_ext_skills.go -src /path/to/eino-ext -dest ./skills/eino-ext -clean
+```
+
+说明:
+
+- `-src` 支持两种形式:
+ - `eino-ext` 仓库根目录(脚本会自动读取 `/skills/...`)
+ - 你已安装 skills 的目录(目录下应包含 `eino-guide/`、`eino-component/` 等子目录)
+- `-dest` 默认是 `./skills/eino-ext`(可以省略)
+
+### 2) 启动 Chapter 9
+
+```bash
+EINO_EXT_SKILLS_DIR=/absolute/path/to/chatwitheino/skills/eino-ext go run ./cmd/ch09
+```
+
+输出示例(节选):
+
+```
+Skills dir: /.../skills/eino-ext
+Enter your message (empty line to exit):
+```
+
+## 在 DeepAgent 中启用 Skill
+
+本章的 “Skill 可被调用” 不是自动发生的,你需要在 Agent 构建时把 `skill` 中间件注册进去。核心就是三步:
+
+1. 用本地 filesystem backend(本章用 `eino-ext/adk/backend/local`)提供文件读取/Glob 能力
+2. 用 `skill.NewBackendFromFilesystem` 把 `EINO_EXT_SKILLS_DIR` 变成一个 Skill Backend
+3. 用 `skill.NewMiddleware` 生成中间件,并把它塞进 DeepAgent 的 `Handlers`
+
+**关键代码片段(注意:这是简化后的代码片段,不能直接运行,完整代码请参考 cmd/ch09/main.go):**
+
+```go
+backend, _ := localbk.NewBackend(ctx, &localbk.Config{})
+
+skillBackend, _ := skill.NewBackendFromFilesystem(ctx, &skill.BackendFromFilesystemConfig{
+ Backend: backend,
+ BaseDir: skillsDir, // = $EINO_EXT_SKILLS_DIR
+})
+skillMiddleware, _ := skill.NewMiddleware(ctx, &skill.Config{
+ Backend: skillBackend,
+})
+
+agent, _ := deep.New(ctx, &deep.Config{
+ ChatModel: cm,
+ Backend: backend,
+ StreamingShell: backend,
+ Handlers: []adk.ChatModelAgentMiddleware{
+ skillMiddleware,
+ // ... 其他中间件,比如 approval/safeTool/retry 等
+ },
+})
+```
+
+补充说明:
+
+- 本 quickstart 为了保证 “没配置 skills 也能跑”,在代码里对 `EINO_EXT_SKILLS_DIR` 做了存在性检查:目录存在才注册 `skillMiddleware`;否则跳过(此时仍可对话与使用 RAG 工具)。
+- Skill 工具的入参是一个 JSON:`{"skill": ""}`,例如 `{"skill":"eino-guide"}`。
+
+## 快速验证(推荐)
+
+启动后输入一条指令,明确要求模型调用 skill 工具(用于验证 skills 已被发现且可被加载):
+
+```
+Use the skill tool with skill="eino-guide" and tell me what the entry point is for getting started.
+```
+
+你应当能在控制台看到类似输出:
+
+- `[tool result] Launching skill: eino-guide`
+- Tool result 中包含 `Base directory for this skill: .../eino-guide`
+
+## 你会看到什么
+
+- 当模型调用 skill 工具时,控制台会打印:
+ - `[tool call] ...`
+ - `[tool result] ...`(对结果做了截断展示)
+- 会话保存在 `SESSION_DIR`(默认 `./data/sessions`),支持恢复:
+ - `go run ./cmd/ch09 --session `
diff --git a/content/zh/docs/eino/quick_start/simple_llm_application.md b/content/zh/docs/eino/quick_start/simple_llm_application.md
deleted file mode 100644
index ee737a0ccb6..00000000000
--- a/content/zh/docs/eino/quick_start/simple_llm_application.md
+++ /dev/null
@@ -1,207 +0,0 @@
----
-Description: ""
-date: "2026-01-20"
-lastmod: ""
-tags: []
-title: 实现一个最简 LLM 应用
-weight: 1
----
-
-本指南将帮助你快速上手使用 Eino 框架中的 ChatModel 构建一个简单的 LLM 应用。我们将通过实现一个"程序员鼓励师"的例子,来展示如何使用 ChatModel。
-
-> 💡
-> 本文中示例的代码片段详见:[eino-examples/quickstart/chat](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chat)
-
-## **ChatModel 简介**
-
-ChatModel 是 Eino 框架中对对话大模型的抽象,它提供了统一的接口来与不同的大模型服务(如 OpenAI、Ollama 等)进行交互。
-
-> 组件更详细的介绍参考: [Eino: ChatModel 使用说明](/zh/docs/eino/core_modules/components/chat_model_guide)
-
-## **Messages 的结构和使用**
-
-在 Eino 中,对话是通过 `schema.Message` 来表示的,这是 Eino 对一个对话消息的抽象定义。每个 Message 包含以下重要字段:
-
-- `Role`: 消息的角色,可以是:
- - `system`: 系统指令,用于设定模型的行为和角色
- - `user`: 用户的输入
- - `assistant`: 模型的回复
- - `tool`: 工具调用的结果
-- `Content`: 消息的具体内容
-
-## **实现程序员鼓励师**
-
-让我们通过实现一个程序员鼓励师来学习如何使用 ChatModel。这个助手不仅能提供技术建议,还能在程序员感到难过时给予心理支持。
-
-### 创建对话模板并生成消息
-
-Eino 提供了强大的模板化功能来构建要输入给大模型的消息:
-
-1. 模版渲染,支持三种模版格式:
-
- - FString:Python 风格的简单字符串格式化(例如:"你好,{name}!")
- - Jinja2:支持丰富表达式的 Jinja2 风格模板(例如:"你好,{{name}}!")
- - GoTemplate:Go 语言内置的 text/template 格式(例如:"你好,{{.name}}!")
-2. 消息占位符:支持插入一组消息(如对话历史)
-
-```go
-// optional=false 表示必需的消息列表,在模版输入中找不到对应变量会报错
-schema.MessagesPlaceholder("chat_history", false)
-```
-
-> 更详细的组件介绍可参考: [Eino: ChatTemplate 使用说明](/zh/docs/eino/core_modules/components/chat_template_guide)
-
-下面是完整的 FString 格式 + 消息占位符的对话模板创建及使用代码:
-
-```go
-// eino-examples/quickstart/chat/template.go
-
-import (
- "context"
-
- "github.com/cloudwego/eino/components/prompt"
- "github.com/cloudwego/eino/schema"
-)
-
-// 创建模板,使用 FString 格式
-template := prompt.FromMessages(schema.FString,
- // 系统消息模板
- schema.SystemMessage("你是一个{role}。你需要用{style}的语气回答问题。你的目标是帮助程序员保持积极乐观的心态,提供技术建议的同时也要关注他们的心理健康。"),
-
- // 插入需要的对话历史(新对话的话这里不填)
- schema.MessagesPlaceholder("chat_history", true),
-
- // 用户消息模板
- schema.UserMessage("问题: {question}"),
-)
-
-// 使用模板生成消息
-messages, err := template.Format(context.Background(), map[string]any{
- "role": "程序员鼓励师",
- "style": "积极、温暖且专业",
- "question": "我的代码一直报错,感觉好沮丧,该怎么办?",
- // 对话历史(这个例子里模拟两轮对话历史)
- "chat_history": []*schema.Message{
- schema.UserMessage("你好"),
- schema.AssistantMessage("嘿!我是你的程序员鼓励师!记住,每个优秀的程序员都是从 Debug 中成长起来的。有什么我可以帮你的吗?", nil),
- schema.UserMessage("我觉得自己写的代码太烂了"),
- schema.AssistantMessage("每个程序员都经历过这个阶段!重要的是你在不断学习和进步。让我们一起看看代码,我相信通过重构和优化,它会变得更好。记住,Rome wasn't built in a day,代码质量是通过持续改进来提升的。", nil),
- },
-})
-```
-
-### 创建 ChatModel
-
-ChatModel 是 Eino 框架中最核心的组件之一,它提供了与各种大语言模型交互的统一接口。Eino 目前支持以下大语言模型的实现:
-
-- OpenAI:支持 GPT-3.5/GPT-4 等模型 (同样支持 azure 提供的 openai 服务)
-- Ollama:支持本地部署的开源模型
-- Ark:火山引擎上的模型服务 (例如字节的豆包大模型)
-- 更多模型正在支持中
-
-> 支持的模型可以参考:[Eino: 生态集成](/zh/docs/eino/ecosystem_integration)
-
-下面我们以 OpenAI 和 Ollama 为例,展示如何创建和使用 ChatModel:
-
-#### **OpenAI (和下方 ollama 2 选 1)**
-
-```go
-// eino-examples/quickstart/chat/openai.go
-
-import (
- "os"
-
- "github.com/cloudwego/eino-ext/components/model/openai"
-)
-
-chatModel, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
- Model: "gpt-4o", // 使用的模型版本
- APIKey: os.Getenv("OPENAI_API_KEY"), // OpenAI API 密钥
-})
-```
-
-> OpenAI ChatModel 的详细信息可以参考:[ChatModel - OpenAI](https://github.com/cloudwego/eino-ext/blob/main/components/model/openai/README_zh.md)
-
-#### **Ollama(和上方 openai 2 选 1)**
-
-Ollama 支持在本地运行开源模型,适合对数据隐私有要求或需要离线使用的场景。
-
-```go
-// eino-examples/quickstart/chat/ollama.go
-
-import (
- "github.com/cloudwego/eino-ext/components/model/ollama"
-)
-
-
-chatModel, err := ollama.NewChatModel(ctx, &ollama.ChatModelConfig{
- BaseURL: "http://localhost:11434", // Ollama 服务地址
- Model: "llama2", // 模型名称
-})
-```
-
-> Ollama ChatModel 的详细信息可以参考:[ChatModel - Ollama](https://github.com/cloudwego/eino-ext/blob/main/components/model/ollama/README_zh.md)
-
-Eino 为大模型提供了统一的 ChatModel 抽象,并提供了开箱即用的各类 LLM 实现,因此业务代码可以无需关注模型实现细节从而专注业务逻辑编写,模型实现迭代时不会影响核心业务逻辑,这意味着开发者可以轻松地在不同的模型之间切换,而无需修改大量代码。
-
-### 运行 ChatModel
-
-经过前两步得到 ChatModel 的输入 messages 和初始化完成后的 ChatModel 实例后,可以开始尝试运行 ChatModel 了。Eino ChatModel 提供了两种运行模式:输出完整消息(generate)和输出消息流(stream):
-
-```go
-// eino-examples/quickstart/chat/generate.go
-
-/*** create messages
-* messages, err := xxx
-*/
-
-/*** create chat model
-* chatModel, err := xxx
-*/
-
-result, err := chatModel.Generate(ctx, messages)
-streamResult, err := chatModel.Stream(ctx, messages)
-```
-
-在实际应用中,有很多场景需要使用流式响应,主要的场景例如「提升用户体验」:stream 运行模式让 ChatModel 提供类似打字机的输出效果,使用户更早得到模型响应。
-
-Eino 中对流式输出的处理方式如下:
-
-```go
-// eino-examples/quickstart/chat/stream.go
-
-import (
- "io"
- "log"
-
- "github.com/cloudwego/eino/schema"
-)
-
-func reportStream(sr *schema.StreamReader[*schema.Message]) {
- defer sr.Close()
-
- i := 0
- for {
- message, err := sr.Recv()
- if err == io.EOF { // 流式输出结束
- return
- }
- if err != nil {
- log.Fatalf("recv failed: %v", err)
- }
- log.Printf("message[%d]: %+v\n", i, message)
- i++
- }
-}
-```
-
-完整实现参见:[eino-examples/quickstart/chat/main.go](https://github.com/cloudwego/eino-examples/blob/main/quickstart/chat/main.go)
-
-## **总结**
-
-本示例通过一个程序员鼓励师的案例,展示了如何使用 Eino 框架构建 LLM 应用。从 ChatModel 的创建到消息模板的使用,再到实际的对话实现,相信你已经对 Eino 框架有了基本的了解。无论是选择 OpenAI、Ollama 还是其他模型实现,Eino 都提供了统一且简单的使用方式。希望这个示例能帮助你快速开始构建自己的 LLM 应用。
-
-## **关联阅读**
-
-- 快速开始
- - [Agent-让大模型拥有双手](/zh/docs/eino/quick_start/agent_llm_with_tools)
diff --git a/content/zh/docs/eino/release_notes_and_migration/v02_second_release.md b/content/zh/docs/eino/release_notes_and_migration/v02_second_release.md
index 75cf940695b..fbda1b7ed12 100644
--- a/content/zh/docs/eino/release_notes_and_migration/v02_second_release.md
+++ b/content/zh/docs/eino/release_notes_and_migration/v02_second_release.md
@@ -74,7 +74,7 @@ weight: 2
### BugFix
-- Fixed the SSTI vulnerability in the Jinja chat template(langchaingo gonja 模板注入)
+- Fixed the SSTI vulnerability in the Jinja chat template(langchaingo 存在 gonja 模板注入)
## v0.2.0