### Clone Eino Examples Repository Source: https://www.cloudwego.io/zh/docs/eino/quick_start/chapter_01_chatmodel_and_message Obtain the necessary example code for the quickstart guide by cloning the official Eino examples repository. ```bash git clone https://github.com/cloudwego/eino-examples.git cd eino-examples/quickstart/chateino ``` -------------------------------- ### Quick Start: PDF Skill Example Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/middleware_skill A step-by-step guide to setting up a PDF skill using the Skill Middleware, including creating a local backend and integrating with an Agent. ```APIDOC ## Quick Start: PDF Skill Example This example demonstrates loading a PDF skill from local files. ### Directory Structure ``` workdir/ ├── skills/ │ └── pdf/ │ ├── scripts │ │ └── analyze.py │ └── SKILL.md └── other files ``` ### Steps 1. **Create Local Filesystem Backend and Skill Middleware**: ```go import ( "github.com/cloudwego/eino/adk/middlewares/skill" "github.com/cloudwego/eino-ext/adk/backend/local" ) ctx := context.Background() be, err := local.NewBackend(ctx, &local.Config{}) if err != nil { log.Fatal(err) } skillBackend, err := skill.NewBackendFromFilesystem(ctx, &skill.BackendFromFilesystemConfig{ Backend: be, BaseDir: skillsDir, // Replace with your skills directory path }) if err != nil { log.Fatalf("Failed to create skill backend: %v", err) } sm, err := skill.NewMiddleware(ctx, &skill.Config{ Backend: skillBackend, }) if err != nil { log.Fatalf("Failed to create skill middleware: %v", err) } ``` 2. **Create Filesystem Middleware** (for reading skill files and executing scripts): ```go import ( "github.com/cloudwego/eino/adk/middlewares/filesystem" ) fsm, err := filesystem.New(ctx, &filesystem.MiddlewareConfig{ Backend: be, StreamingShell: be, }) if err != nil { log.Fatalf("Failed to create filesystem middleware: %v", err) } ``` 3. **Create Agent and Configure Middlewares**: ```go agent, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{ Name: "LogAnalysisAgent", Description: "An agent that can analyze logs", Instruction: "You are a helpful assistant.", Model: cm, // Replace with your model instance Handlers: []adk.ChatModelAgentMiddleware{fsm, sm}, }) if err != nil { log.Fatalf("Failed to create agent: %v", err) } ``` 4. **Call Agent and Observe Results**: ```go runner := adk.NewRunner(ctx, adk.RunnerConfig{ Agent: agent, }) input := fmt.Sprintf("Analyze the %s file", filepath.Join(workDir, "test.log")) log.Println("User: ", input) iterator := runner.Query(ctx, input) for { event, ok := iterator.Next() if !ok { break } if event.Err != nil { log.Printf("Error: %v\n", event.Err) break } prints.Event(event) } ``` ``` -------------------------------- ### Install Eino and OpenAI Component Source: https://www.cloudwego.io/zh/docs/eino/core_modules/chain_and_graph_orchestration/chain_graph_introduction Install the necessary Eino and OpenAI components using go get. ```bash go get github.com/cloudwego/eino-ext/components/model/openai@latest go get github.com/cloudwego/eino@latest ``` -------------------------------- ### Simplified CozeLoop Setup in Main Source: https://www.cloudwego.io/zh/docs/eino/quick_start/chapter_06_callback_and_trace A simplified code snippet for setting up CozeLoop tracing within the main function. It checks for environment variables, creates a new client, and registers the handler. Note that this is a simplified example and requires a full context. ```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)) } ``` -------------------------------- ### Install Local Backend Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/filesystem_backend/backend_%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F Use 'go get' to install the local backend package. Ensure you are using the correct version for your EINO installation. ```go go get github.com/cloudwego/eino-ext/adk/backend/local ``` -------------------------------- ### Local Backend Installation Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/filesystem_backend/backend_%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F Instructions on how to install the Local Backend package using go get. ```APIDOC ## Installation ```bash go get github.com/cloudwego/eino-ext/adk/backend/local ``` ``` -------------------------------- ### Local Backend Quick Start Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/filesystem_backend/backend_%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F Basic usage examples for the Local Backend, including file writing, reading, and command execution. ```APIDOC ## Quick Start ### Basic Usage ```go import ( "context" "github.com/cloudwego/eino-ext/adk/backend/local" "github.com/cloudwego/eino/adk/filesystem" ) func main() { ctx := context.Background() backend, err := local.NewBackend(ctx, &local.Config{}) if err != nil { panic(err) } // Write file (must be absolute path) err = backend.Write(ctx, &filesystem.WriteRequest{ FilePath: "/tmp/hello.txt", Content: "Hello, Local Backend!", }) // Read file fcontent, err := backend.Read(ctx, &filesystem.ReadRequest{ FilePath: "/tmp/hello.txt", }) fmt.Println(fcontent.Content) } ``` ``` -------------------------------- ### Full Prompt Implementation with Callbacks and Options Source: https://www.cloudwego.io/zh/docs/eino/core_modules/components/agentic_chat_template_guide A complete example of a prompt component implementing the Format method, handling custom options, and triggering callbacks at various stages (start, error, end). ```go type MyPrompt struct { templates []schema.AgenticMessagesTemplate formatType schema.FormatType strictMode bool defaultValues map[string]string } func NewMyPrompt(config *MyPromptConfig) (*MyPrompt, error) { return &MyPrompt{ templates: config.Templates, formatType: config.FormatType, strictMode: config.DefaultStrictMode, defaultValues: config.DefaultValues, }, nil } func (p *MyPrompt) Format(ctx context.Context, vs map[string]any, opts ...prompt.Option) ([]*schema.AgenticMessage, error) { // 1. 处理 Option options := &MyPromptOptions{ StrictMode: p.strictMode, DefaultValues: p.defaultValues, } options = prompt.GetImplSpecificOptions(options, opts...) // 2. 获取 callback manager cm := callbacks.ManagerFromContext(ctx) // 3. 开始格式化前的回调 ctx = cm.OnStart(ctx, info, &prompt.AgenticCallbackInput{ Variables: vs, Templates: p.templates, }) // 4. 执行格式化逻辑 messages, err := p.doFormat(ctx, vs, options) // 5. 处理错误和完成回调 if err != nil { ctx = cm.OnError(ctx, info, err) return nil, err } ctx = cm.OnEnd(ctx, info, &prompt.AgenticCallbackOutput{ Result: messages, Templates: p.templates, }) return messages, nil } func (p *MyPrompt) doFormat(ctx context.Context, vs map[string]any, opts *MyPromptOptions) ([]*schema.AgenticMessage, error) { // 实现自己定义逻辑 return messages, nil } ``` -------------------------------- ### Run Eino Agent Server Source: https://www.cloudwego.io/zh/docs/eino/overview/bytedance_eino_practice Start the Eino Agent Server by navigating to the eino assistant example directory, sourcing the .env file, and running the Go command. This command is executed from the eino_assistant directory to access the data directory. ```bash cd eino-examples/eino_assistant # 进入 eino assistant 的 example 中 # 修改 .env 中所需的环境变量 (大模型信息、trace 平台信息) source .env # 为了使用 data 目录,需要在 eino_assistant 目录下执行指令 go run cmd/einoagent/*.go ``` -------------------------------- ### Install Agentkit Backend Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/filesystem_backend/backend_ark_agentkit_sandbox Use go get to add the dependency to your project. ```bash go get github.com/cloudwego/eino-ext/adk/backend/agentkit ``` -------------------------------- ### Run Chapter 5 Example Source: https://www.cloudwego.io/zh/docs/eino/quick_start/chapter_05_middleware Command to run the Chapter 5 example, including setting the project root directory. ```bash # 设置项目根目录 export PROJECT_ROOT=/path/to/your/project go run ./cmd/ch05 ``` -------------------------------- ### Install Eino and OpenAI Model Source: https://www.cloudwego.io/zh/docs/eino/core_modules/flow_integration_components/react_agent_manual Install the eino library and the OpenAI model component using go get. ```go go get github.com/cloudwego/eino-ext/components/model/openai@latest go get github.com/cloudwego/eino@latest ``` -------------------------------- ### Run Graph Tool Example Source: https://www.cloudwego.io/zh/docs/eino/quick_start/chapter_08_graph_tool Execute the Graph Tool example by setting the project root and running the main Go program. ```bash # Set project root export PROJECT_ROOT=/path/to/your/project go run ./cmd/ch08 ``` -------------------------------- ### Run ChatWithEino Example Source: https://www.cloudwego.io/zh/docs/eino/quick_start/chapter_01_chatmodel_and_message Execute the chat assistant example from the command line, providing a user query as an argument. The output will be streamed incrementally. ```bash go run ./cmd/ch01 -- "用一句话解释 Eino 的 Component 设计解决了什么问题?" ``` -------------------------------- ### Main Function Setup with Optional CozeLoop Integration Source: https://www.cloudwego.io/zh/docs/eino/quick_start/chapter_06_callback_and_trace Demonstrates the main function's setup, including optional CozeLoop integration. If CozeLoop is set up, it ensures the client is closed after a delay upon program exit. This snippet is a simplified version and not directly runnable. ```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 并运行... } ``` -------------------------------- ### InMemoryBackend Usage Example Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/filesystem_backend Example demonstrating how to use the InMemoryBackend for file operations. ```Go import ( "context" "github.com/cloudwego/eino/adk/filesystem" ) func main() { ctx := context.Background() backend := filesystem.NewInMemoryBackend() // Write a file err := backend.Write(ctx, &filesystem.WriteRequest{ FilePath: "/example/test.txt", Content: "Hello, World!\nLine 2\nLine 3", }) if err != nil { // Handle error } // Read a file (supports pagination) content, err := backend.Read(ctx, &filesystem.ReadRequest{ FilePath: "/example/test.txt", Offset: 1, Limit: 10, }) if err != nil { // Handle error } // Process content.Content // List directory contents files, err := backend.LsInfo(ctx, &filesystem.LsInfoRequest{ Path: "/example", }) if err != nil { // Handle error } // Process files list // Search content (supports regex) matches, err := backend.GrepRaw(ctx, &filesystem.GrepRequest{ Pattern: "Hello", Path: "/example", }) if err != nil { // Handle error } // Process matches // Edit file content err = backend.Edit(ctx, &filesystem.EditRequest{ FilePath: "/example/test.txt", OldString: "Hello", NewString: "Hi", ReplaceAll: false, }) if err != nil { // Handle error } } ``` -------------------------------- ### AgentsMD Middleware - Quick Start Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/middleware_agentsmd A minimal example demonstrating how to initialize and use the AgentsMD middleware with a local file backend. ```APIDOC ## AgentsMD Middleware - Quick Start This snippet shows the basic setup for the AgentsMD middleware. ### Method Initialization ### Endpoint N/A (Middleware setup) ### Parameters #### Request Body - **ctx** (context.Context) - Required - The context for the operation. - **config** (*agentsmd.Config) - Required - Configuration for the middleware. - **Backend** (Backend) - Required - The backend for file access. - **AgentsMDFiles** ([]string) - Required - List of Agents.md file paths. - **AllAgentsMDMaxBytes** (int) - Optional - Maximum total byte size for all loaded files. - **OnLoadWarning** (func(string, error)) - Optional - Callback for non-fatal loading errors. ### Request Example ```go package main import ( "context" "fmt" "github.com/cloudwego/eino/adk" "github.com/cloudwego/eino/adk/middlewares/agentsmd" ) func main() { ctx := context.Background() // 1. Prepare Backend (file reading backend) backend := NewLocalFileBackend("/path/to/project") // 2. Create agentsmd middleware mw, err := agentsmd.New(ctx, &agentsmd.Config{ Backend: backend, AgentsMDFiles: []string{"/home/user/project/agents.md"}, }) if err != nil { panic(err) } // 3. Configure middleware in Agent // agent := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{ // Middlewares: []adk.ChatModelAgentMiddleware{mw}, // }) _ = mw fmt.Println("agentsmd middleware created successfully") } ``` ### Response #### Success Response (200) - **middleware** (*agentsmd.Middleware) - The initialized middleware instance. - **error** (error) - An error if initialization fails. #### Response Example (Initialization does not return a direct response body in this context, errors are returned.) ``` -------------------------------- ### Custom Backend Implementation Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/filesystem_backend Example of how to implement a custom Backend. ```APIDOC ## Custom Backend Implementation ### Description To integrate with custom storage solutions (like OSS, databases, etc.), implement the `Backend` interface. ### Example ```go type MyBackend struct { // Custom fields for your storage integration } func (b *MyBackend) LsInfo(ctx context.Context, req *filesystem.LsInfoRequest) ([]filesystem.FileInfo, error) { // Implement custom logic for listing directory information return nil, nil // Placeholder } func (b *MyBackend) Read(ctx context.Context, req *filesystem.ReadRequest) (*filesystem.FileContent, error) { // Implement custom logic for reading file content return nil, nil // Placeholder } // Implement the remaining methods of the Backend interface (Write, Edit, GrepRaw, GlobInfo) // Optionally, implement Shell or StreamingShell interfaces if command execution is needed. ``` ``` -------------------------------- ### Complete Custom Indexer Implementation Example Source: https://www.cloudwego.io/zh/docs/eino/core_modules/components/indexer_guide A comprehensive example demonstrating the structure of a custom `MyIndexer`, including its constructor, `Store` method with option and callback handling, and the `doStore` logic for embedding and storing documents. ```go type MyIndexer struct { batchSize int embedder embedding.Embedder } func NewMyIndexer(config *MyIndexerConfig) (*MyIndexer, error) { return &MyIndexer{ batchSize: config.DefaultBatchSize, embedder: config.DefaultEmbedder, }, nil } func (i *MyIndexer) Store(ctx context.Context, docs []*schema.Document, opts ...indexer.Option) ([]string, error) { options := &indexer.Options{}, options = indexer.GetCommonOptions(options, opts...) cm := callbacks.ManagerFromContext(ctx) ctx = cm.OnStart(ctx, info, &indexer.CallbackInput{ Docs: docs, }) ids, err := i.doStore(ctx, docs, options) if err != nil { ctx = cm.OnError(ctx, info, err) return nil, err } ctx = cm.OnEnd(ctx, info, &indexer.CallbackOutput{ IDs: ids, }) return ids, nil } func (i *MyIndexer) doStore(ctx context.Context, docs []*schema.Document, opts *indexer.Options) ([]string, error) { if opts.Embedding != nil { texts := make([]string, len(docs)) for j, doc := range docs { texts[j] = doc.Content } vectors, err := opts.Embedding.EmbedStrings(ctx, texts) if err != nil { return nil, err } for j, doc := range docs { doc.WithVector(vectors[j]) } } return ids, nil } ``` -------------------------------- ### Initialize MCPToolApprovalResponse Source: https://www.cloudwego.io/zh/docs/eino/core_modules/components/agentic_chat_model_guide Example of responding to an approval request. ```go approvalResp := &schema.MCPToolApprovalResponse{ ApprovalRequestID: "approval_789", Approve: true, Reason: "已确认删除非活跃用户", } ``` -------------------------------- ### Complete Eino Graph with State Example Source: https://www.cloudwego.io/zh/docs/eino/core_modules/chain_and_graph_orchestration/chain_graph_introduction A full example demonstrating the creation of a graph with local state, adding nodes with state handlers, and invoking the graph. ```go package main import ( "context" "errors" "io" "runtime/debug" "strings" "unicode/utf8" "github.com/cloudwego/eino/compose" "github.com/cloudwego/eino/schema" "github.com/cloudwego/eino/utils/safe" "github.com/cloudwego/eino-examples/internal/logs" ) func main() { ctx := context.Background() const ( nodeOfL1 = "invokable" nodeOfL2 = "streamable" nodeOfL3 = "transformable" ) type testState struct { ms []string } gen := func(ctx context.Context) *testState { return &testState{} } sg := compose.NewGraph[string, string](compose.WithGenLocalState(gen)) l1 := compose.InvokableLambda(func(ctx context.Context, in string) (out string, err error) { return "InvokableLambda: " + in, nil }) l1StateToInput := func(ctx context.Context, in string, state *testState) (string, error) { state.ms = append(state.ms, in) return in, nil } l1StateToOutput := func(ctx context.Context, out string, state *testState) (string, error) { state.ms = append(state.ms, out) return out, nil } _ = sg.AddLambdaNode(nodeOfL1, l1, compose.WithStatePreHandler(l1StateToInput), compose.WithStatePostHandler(l1StateToOutput)) l2 := compose.StreamableLambda(func(ctx context.Context, input string) (output *schema.StreamReader[string], err error) { outStr := "StreamableLambda: " + input sr, sw := schema.Pipe[string](utf8.RuneCountInString(outStr)) // nolint: byted_goroutine_recover go func() { for _, field := range strings.Fields(outStr) { sw.Send(field+" ", nil) } sw.Close() }() return sr, nil }) l2StateToOutput := func(ctx context.Context, out string, state *testState) (string, error) { state.ms = append(state.ms, out) return out, nil } _ = sg.AddLambdaNode(nodeOfL2, l2, compose.WithStatePostHandler(l2StateToOutput)) l3 := compose.TransformableLambda(func(ctx context.Context, input *schema.StreamReader[string]) ( output *schema.StreamReader[string], err error) { prefix := "TransformableLambda: " sr, sw := schema.Pipe[string](20) go func() { defer func() { panicErr := recover() if panicErr != nil { err := safe.NewPanicErr(panicErr, debug.Stack()) logs.Errorf("panic occurs: %v\n", err) } }() for _, field := range strings.Fields(prefix) { sw.Send(field+" ", nil) } for { chunk, err := input.Recv() if err != nil { if err == io.EOF { break } // TODO: how to trace this kind of error in the goroutine of processing sw sw.Send(chunk, err) break } sw.Send(chunk, nil) } sw.Close() }() return sr, nil }) l3StateToOutput := func(ctx context.Context, out string, state *testState) (string, error) { state.ms = append(state.ms, out) logs.Infof("state result: ") for idx, m := range state.ms { logs.Infof(" %vth: %v", idx, m) } return out, nil } _ = sg.AddLambdaNode(nodeOfL3, l3, compose.WithStatePostHandler(l3StateToOutput)) _ = sg.AddEdge(compose.START, nodeOfL1) _ = sg.AddEdge(nodeOfL1, nodeOfL2) _ = sg.AddEdge(nodeOfL2, nodeOfL3) _ = sg.AddEdge(nodeOfL3, compose.END) run, err := sg.Compile(ctx) if err != nil { logs.Errorf("sg.Compile failed, err=%v", err) return } out, err := run.Invoke(ctx, "how are you") if err != nil { ``` -------------------------------- ### API Reference Examples: Edit, Execute, ExecuteStreaming Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/filesystem_backend/backend_%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F Examples for editing file content, executing shell commands, and streaming command output. Note that ExecuteStreaming requires a loop to process the output. ```go // 编辑文件 backend.Edit(ctx, &filesystem.EditRequest{ FilePath: "/tmp/file.txt", OldString: "old", NewString: "new", ReplaceAll: true, }) // 执行命令 result, _ := backend.Execute(ctx, &filesystem.ExecuteRequest{ Command: "ls -la /tmp", }) // 流式执行 reader, _ := backend.ExecuteStreaming(ctx, &filesystem.ExecuteRequest{ Command: "tail -f /var/log/app.log", }) for { resp, err := reader.Recv() if err == io.EOF { break } fmt.Print(resp.Stdout) } ``` -------------------------------- ### Initialize MCPToolApprovalRequest Source: https://www.cloudwego.io/zh/docs/eino/core_modules/components/agentic_chat_model_guide Example of creating an approval request for a tool execution. ```go approvalReq := &schema.MCPToolApprovalRequest{ ID: "approval_20260112_001", Name: "delete_records", Arguments: `{"table": "users", "condition": "inactive=true", "estimated_count": 150}`, ServerLabel: "database-server", } ``` -------------------------------- ### Simple Workflow Source: https://www.cloudwego.io/zh/docs/eino/cookbook The simplest Workflow example, equivalent to a Graph. ```Go package main import ( "context" "github.com/cloudwego/eino/internal/run" "github.com/cloudwego/eino/internal/run/compose" ) func main() { compose.Workflow( compose.Step("step1", compose.Prompt("Hello"), compose.ChatModel("gpt-3.5-turbo")), compose.Step("step2", compose.Prompt("World"), compose.ChatModel("gpt-3.5-turbo")), ).Run(context.Background()) } ``` -------------------------------- ### API Reference Examples: LsInfo, Read, GrepRaw, GlobInfo Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/filesystem_backend/backend_%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F Examples demonstrating how to use LsInfo to list directory contents, Read for file content retrieval with pagination, GrepRaw for literal pattern searching within files, and GlobInfo for finding files matching a pattern. ```go // 列出目录 files, _ := backend.LsInfo(ctx, &filesystem.LsInfoRequest{ Path: "/home/user", }) // 读取文件(分页) fcontent, _ := backend.Read(ctx, &filesystem.ReadRequest{ FilePath: "/path/to/file.txt", Offset: 0, Limit: 50, }) // 搜索内容(字面量匹配,非正则) matches, _ := backend.GrepRaw(ctx, &filesystem.GrepRequest{ Path: "/home/user/project", Pattern: "TODO", Glob: "*.go", }) // 查找文件 files, _ := backend.GlobInfo(ctx, &filesystem.GlobInfoRequest{ Path: "/home/user", Pattern: "**/*.go", }) ``` -------------------------------- ### Create MCPToolCall Source: https://www.cloudwego.io/zh/docs/eino/core_modules/components/agentic_chat_model_guide Example of initializing an MCPToolCall instance. ```go mcpCall := &schema.MCPToolCall{ ServerLabel: "database-server", CallID: "mcp_call_456", Name: "execute_query", Arguments: `{"sql": "SELECT * FROM users LIMIT 10"}`, } ``` -------------------------------- ### Create Local Filesystem Backend and Skill Middleware Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/middleware_skill This example demonstrates creating a local filesystem backend and then using it to initialize the Skill Middleware. Ensure the `skillsDir` variable is correctly set. ```go import ( "github.com/cloudwego/eino/adk/middlewares/skill" "github.com/cloudwego/eino-ext/adk/backend/local" ) ctx := context.Background() be, err := local.NewBackend(ctx, &local.Config{}) if err != nil { log.Fatal(err) } skillBackend, err := skill.NewBackendFromFilesystem(ctx, &skill.BackendFromFilesystemConfig{ Backend: be, BaseDir: skillsDir, }) if err != nil { log.Fatalf("Failed to create skill backend: %v", err) } sm, err := skill.NewMiddleware(ctx, &skill.Config{ Backend: skillBackend, }) ``` -------------------------------- ### Initialize and Use Sandbox Backend Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/filesystem_backend/backend_ark_agentkit_sandbox Basic usage example for creating a backend and performing file read/write operations. ```go import ( "context" "os" "time" "github.com/cloudwego/eino-ext/adk/backend/agentkit" "github.com/cloudwego/eino/adk/filesystem" ) func main() { ctx := context.Background() backend, err := agentkit.NewSandboxToolBackend(&agentkit.Config{ AccessKeyID: os.Getenv("VOLC_ACCESS_KEY_ID"), SecretAccessKey: os.Getenv("VOLC_SECRET_ACCESS_KEY"), ToolID: os.Getenv("VOLC_TOOL_ID"), UserSessionID: "session-" + time.Now().Format("20060102-150405"), Region: agentkit.RegionOfBeijing, }) if err != nil { panic(err) } // 写入文件 err = backend.Write(ctx, &filesystem.WriteRequest{ FilePath: "/home/gem/hello.txt", Content: "Hello, Sandbox!", }) // 读取文件 fContent, err := backend.Read(ctx, &filesystem.ReadRequest{ FilePath: "/home/gem/hello.txt", }) fmt.Println(fContent.Content) } ``` -------------------------------- ### Install OpenAI Component Source: https://www.cloudwego.io/zh/docs/eino/ecosystem_integration/chat_model/agentic_model_openai Use the go get command to add the agenticopenai package to your project. ```bash go get github.com/cloudwego/eino-ext/components/model/agenticopenai@latest ``` -------------------------------- ### Integrating MCP Tools Source: https://www.cloudwego.io/zh/docs/eino/core_modules/components/tools_node_guide/how_to_create_a_tool Example showing how to retrieve and use tools provided by an MCP server in Eino. ```go import ( "fmt" "log" "context" "github.com/mark3labs/mcp-go/client" mcpp "github.com/cloudwego/eino-ext/components/tool/mcp" ) func getMCPTool(ctx context.Context) []tool.BaseTool { cli, err := client.NewSSEMCPClient("http://localhost:12345/sse") if err != nil { log.Fatal(err) } err = cli.Start(ctx) if err != nil { log.Fatal(err) } initRequest := mcp.InitializeRequest{} initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION initRequest.Params.ClientInfo = mcp.Implementation{ Name: "example-client", Version: "1.0.0", } _, err = cli.Initialize(ctx, initRequest) if err != nil { log.Fatal(err) } tools, err := mcpp.GetTools(ctx, &mcpp.Config{Cli: cli}) if err != nil { log.Fatal(err) } return tools } ``` -------------------------------- ### Configure FieldMapping for Data Transfer Source: https://www.cloudwego.io/zh/docs/eino/quick_start/chapter_08_graph_tool Example of using FieldMapping to transfer specific fields between nodes, including data from the START node and other nodes. ```go wf.AddLambdaNode("answer", answerFunc). AddInputWithOptions("filter", // Get data from the filter node []*compose.FieldMapping{compose.ToField("TopK")}, compose.WithNoDirectDependency()). AddInputWithOptions(compose.START, // Get data from the START node []*compose.FieldMapping{compose.MapFields("Question", "Question")}, compose.WithNoDirectDependency()) ``` -------------------------------- ### Basic Local Backend Usage Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/filesystem_backend/backend_%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F Demonstrates the basic usage of the local backend, including initialization, writing to a file, and reading from a file. File paths must be absolute. ```go import ( "context" "github.com/cloudwego/eino-ext/adk/backend/local" "github.com/cloudwego/eino/adk/filesystem" ) func main() { ctx := context.Background() backend, err := local.NewBackend(ctx, &local.Config{}) if err != nil { panic(err) } // 写入文件(必须是绝对路径) err = backend.Write(ctx, &filesystem.WriteRequest{ FilePath: "/tmp/hello.txt", Content: "Hello, Local Backend!", }) // 读取文件 fcontent, err := backend.Read(ctx, &filesystem.ReadRequest{ FilePath: "/tmp/hello.txt", }) fmt.Println(fcontent.Content) } ``` -------------------------------- ### Implement ChatTemplate Callbacks Source: https://www.cloudwego.io/zh/docs/eino/core_modules/components/chat_template_guide Provides an example of implementing custom callback handlers for the Prompt component. This allows for intercepting and logging events during template formatting, such as start and end of the process. ```go import ( "context" callbackHelper "github.com/cloudwego/eino/utils/callbacks" "github.com/cloudwego/eino/callbacks" "github.com/cloudwego/eino/compose" "github.com/cloudwego/eino/components/prompt" ) // 创建 callback handler handler := &callbackHelper.PromptCallbackHandler{ OnStart: func(ctx context.Context, info *callbacks.RunInfo, input *prompt.CallbackInput) context.Context { fmt.Printf("开始格式化模板,变量: %v\n", input.Variables) return ctx }, OnEnd: func(ctx context.Context, info *callbacks.RunInfo, output *prompt.CallbackOutput) context.Context { fmt.Printf("模板格式化完成,生成消息数量: %d\n", len(output.Result)) return ctx }, } // 使用 callback handler helper := callbackHelper.NewHandlerHelper(). Prompt(handler). Handler() // 在运行时使用 runnable, err := chain.Compile() if err != nil { return err } result, err := runnable.Invoke(ctx, variables, compose.WithCallbacks(helper)) ``` -------------------------------- ### Implement Custom Callback Handler with HandlerHelper Source: https://www.cloudwego.io/zh/docs/eino/quick_start/chapter_06_callback_and_trace Use HandlerHelper to simplify the implementation of the Handler interface by registering only the desired callbacks. This example shows how to log component start, end, and error events. Register the handler globally using AppendGlobalHandlers. ```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) ``` -------------------------------- ### Install Ark Model Source: https://www.cloudwego.io/zh/docs/eino/core_modules/flow_integration_components/react_agent_manual Install the Ark model component for use with the eino framework. ```go go get github.com/cloudwego/eino-ext/components/model/ark@latest ``` -------------------------------- ### Standard Tool Usage Example Source: https://www.cloudwego.io/zh/docs/eino/core_modules/components/tools_node_guide Example demonstrating how to use the standard Tool component with a ToolsNode. ```APIDOC ## Standard Tool Usage ### Description This example shows how to create and invoke a `ToolsNode` with standard tools. ### Code Example ```go import ( "github.com/cloudwego/eino/components/tool" "github.com/cloudwego/eino/compose" "github.com/cloudwego/eino/schema" ) // Assume searchTool, weatherTool, calculatorTool are defined elsewhere // Create a tool node toolsNode := compose.NewToolNode([]tool.Tool{ searchTool, weatherTool, calculatorTool, }) // Mock LLM output as input input := &schema.Message{ Role: schema.Assistant, ToolCalls: []schema.ToolCall{ { Function: schema.FunctionCall{ Name: "weather", Arguments: `{\"city\": \"深圳\", \"date\": \"tomorrow\"}`, }, }, }, } toolMessages, err := toolsNode.Invoke(ctx, input) ``` ``` -------------------------------- ### Configure Workflow with Static Values and Branching Source: https://www.cloudwego.io/zh/docs/eino/core_modules/chain_and_graph_orchestration/workflow_orchestration_framework This example demonstrates setting static 'Budget' values for two bidder nodes and configuring a branch. It shows how to compile and invoke the workflow. ```go func main() { type bidInput struct { Price float64 Budget float64 } bidder := func(ctx context.Context, in bidInput) (float64, error) { if in.Price >= in.Budget { return in.Budget, nil } return in.Price + rand.Float64()*in.Budget, nil } wf := compose.NewWorkflow[float64, map[string]float64]() wf.AddLambdaNode("b1", compose.InvokableLambda(bidder)). AddInput(compose.START, compose.ToField("Price")), // set 'Budget' field to 3.0 for b1 SetStaticValue([]string{"Budget"}, 3.0) // add a branch just like adding branch in Graph. wf.AddBranch("b1", compose.NewGraphBranch(func(ctx context.Context, in float64) (string, error) { if in > 5.0 { return compose.END, nil } return "b2", nil }, map[string]bool{compose.END: true, "b2": true})) wf.AddLambdaNode("b2", compose.InvokableLambda(bidder)). // b2 executes strictly after b1, but does not rely on b1's output, // which means b2 depends on b1, but no data passing between them. AddDependency("b1"). AddInputWithOptions(compose.START, []*compose.FieldMapping{compose.ToField("Price")}, compose.WithNoDirectDependency()). // set 'Budget' field to 4.0 for b2 SetStaticValue([]string{"Budget"}, 4.0) wf.End().AddInput("b1", compose.ToField("bidder1")), AddInput("b2", compose.ToField("bidder2")) runner, err := wf.Compile(context.Background()) if err != nil { logs.Errorf("workflow compile error: %v", err) return } result, err := runner.Invoke(context.Background(), 3.0) if err != nil { logs.Errorf("workflow run err: %v", err) return } logs.Infof("%v", result) } ``` -------------------------------- ### Graph Tool Output Example Source: https://www.cloudwego.io/zh/docs/eino/quick_start/chapter_08_graph_tool Example of the interaction and output when using the Graph Tool for document analysis. ```text you> Please help me analyze the WebSocket handshake part of the RFC6455 document [assistant] I will help you analyze the document... [tool call] answer_from_document(file_path: "rfc6455.txt", question: "WebSocket handshake process") [tool result] Found 3 relevant snippets, generating answer... [assistant] According to the RFC6455 document, the WebSocket handshake process is as follows... ``` -------------------------------- ### Complete Custom Prompt Implementation Example Source: https://www.cloudwego.io/zh/docs/eino/core_modules/components/chat_template_guide A full implementation of a custom prompt, including its constructor, the `Format` method which handles options and callbacks, and a placeholder for the core formatting logic. ```go type MyPrompt struct { templates []schema.MessagesTemplate formatType schema.FormatType strictMode bool defaultValues map[string]string } func NewMyPrompt(config *MyPromptConfig) (*MyPrompt, error) { return &MyPrompt{ templates: config.Templates, formatType: config.FormatType, strictMode: config.DefaultStrictMode, defaultValues: config.DefaultValues, }, nil } func (p *MyPrompt) Format(ctx context.Context, vs map[string]any, opts ...prompt.Option) ([]*schema.Message, error) { // 1. 处理 Option options := &MyPromptOptions{ StrictMode: p.strictMode, DefaultValues: p.defaultValues, } options = prompt.GetImplSpecificOptions(options, opts...) // 2. 获取 callback manager cm := callbacks.ManagerFromContext(ctx) // 3. 开始格式化前的回调 ctx = cm.OnStart(ctx, info, &prompt.CallbackInput{ Variables: vs, Templates: p.templates, }) // 4. 执行格式化逻辑 messages, err := p.doFormat(ctx, vs, options) // 5. 处理错误和完成回调 if err != nil { ctx = cm.OnError(ctx, info, err) return nil, err } ctx = cm.OnEnd(ctx, info, &prompt.CallbackOutput{ Result: messages, Templates: p.templates, }) return messages, nil } func (p *MyPrompt) doFormat(ctx context.Context, vs map[string]any, opts *MyPromptOptions) ([]*schema.Message, error) { // 实现自己定义逻辑 return messages, nil } ``` -------------------------------- ### Install Eino ADK Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/agent_quickstart Install or upgrade Eino to version 0.5.0 or later to use the ADK features. ```go // stable >= eino@v0.5.0 go get github.com/cloudwego/eino@latest ``` -------------------------------- ### Example AgentEvent with Interrupt Action Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/agent_interface An example of an AgentEvent being sent with an Interrupted action, including custom data for interruption. ```go // 例如 ChatModelAgent 中断时,会发送如下的 AgentEvent: h.Send(&AgentEvent{AgentName: h.agentName, Action: &AgentAction{ Interrupted: &InterruptInfo{ Data: &ChatModelAgentInterruptInfo{Data: data, Info: info}, }, }}) ``` -------------------------------- ### Hello World Agent Source: https://www.cloudwego.io/zh/docs/eino/cookbook The simplest Agent example, demonstrating how to create a basic conversational Agent. -------------------------------- ### WrapModel Example Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/agent_implementation/chat_model Implement WrapModel to intercept and modify model inputs or outputs. This example wraps the model with logging functionality. ```Go func (m *MyMiddleware) WrapModel( ctx context.Context, chatModel model.BaseChatModel, mc *adk.ModelContext, ) (model.BaseChatModel, error) { return &loggingModel{ inner: chatModel, logger: m.logger, }, nil } type loggingModel struct { inner model.BaseChatModel logger *log.Logger } func (m *loggingModel) Generate(ctx context.Context, msgs []*schema.Message, opts ...model.Option) (*schema.Message, error) { m.logger.Printf("Input messages: %d", len(msgs)) resp, err := m.inner.Generate(ctx, msgs, opts...) m.logger.Printf("Output: %v, error: %v", resp != nil, err) return resp, err } func (m *loggingModel) Stream(ctx context.Context, msgs []*schema.Message, opts ...model.Option) (*schema.StreamReader[*schema.Message], error) { return m.inner.Stream(ctx, msgs, opts...) } ``` -------------------------------- ### Enhanced Tool Usage Example (InferEnhancedTool) Source: https://www.cloudwego.io/zh/docs/eino/core_modules/components/tools_node_guide Example demonstrating how to use an enhanced tool with multimodal capabilities using InferEnhancedTool. ```APIDOC ## Enhanced Tool Usage (InferEnhancedTool) ### Description This example demonstrates creating an enhanced tool that returns multimodal content, such as images, using `InferEnhancedTool`. ### Code Example ```go import ( "context" "github.com/cloudwego/eino/components/tool" "github.com/cloudwego/eino/components/tool/utils" "github.com/cloudwego/eino/schema" ) // Define input parameter struct type ImageSearchInput struct { Query string `json:"query" jsonschema:"description=搜索关键词"` } // Create an enhanced tool imageSearchTool, err := utils.InferEnhancedTool( "image_search", "搜索并返回相关图片", func(ctx context.Context, input *ImageSearchInput) (*schema.ToolResult, error) { // Image search logic... imageURL := "https://example.com/image.png" return &schema.ToolResult{ Parts: []schema.ToolOutputPart{ {Type: schema.ToolPartTypeText, Text: "找到以下图片:"}, { Type: schema.ToolPartTypeImage, Image: &schema.ToolOutputImage{ MessagePartCommon: schema.MessagePartCommon{ URL: &imageURL, }, }, }, }, }, nil }, ) ``` ``` -------------------------------- ### Implement BeforeAgent Middleware Logic Source: https://www.cloudwego.io/zh/docs/eino/core_modules/eino_adk/agent_implementation/chat_model Provides an example implementation of the `BeforeAgent` middleware method. It demonstrates how to modify the agent's instruction, add new tools, and configure tools for direct return by creating a copy of the context to avoid modifying the input. ```go func (m *MyMiddleware) BeforeAgent( ctx context.Context, runCtx *adk.ChatModelAgentContext, ) (context.Context, *adk.ChatModelAgentContext, error) { // 拷贝 runCtx,避免修改输入 nRunCtx := *runCtx // 修改指令 nRunCtx.Instruction += "\n\n请始终使用中文回复。" // 添加工具 nRunCtx.Tools = append(runCtx.Tools, myCustomTool) // 设置工具直接返回 nRunCtx.ReturnDirectly["my_tool"] = true return ctx, &nRunCtx, nil } ```