### Clone Eino Examples Repository Source: https://cloudwego.cn/docs/eino/quick_start Clone the Eino examples repository to your local machine to begin the quickstart. ```bash git clone https://github.com/cloudwego/eino-examples.git cd eino-examples/quickstart/chatwitheino ``` -------------------------------- ### Clone Eino Examples Repository Source: https://cloudwego.cn/docs/eino/quick_start/chapter_01_chatmodel_and_message Clone the official Eino examples repository to get started with the quickstart guide. Ensure you have Git installed. ```bash git clone https://github.com/cloudwego/eino-examples.git cd eino-examples/quickstart/chatwitheino ``` -------------------------------- ### Install Eino and OpenAI Components Source: https://cloudwego.cn/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 ``` -------------------------------- ### Install Local Backend Source: https://cloudwego.cn/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 your eino version is compatible. ```go go get github.com/cloudwego/eino-ext/adk/backend/local ``` -------------------------------- ### Quick Start: AgenticModel OpenAI Example Source: https://cloudwego.cn/docs/eino/ecosystem_integration/chat_model/agentic_model_openai Demonstrates initializing and using the AgenticModel with OpenAI, including setting up API credentials, defining tools, and generating a response. Ensure OPENAI_MODEL_ID and OPENAI_API_KEY environment variables are set. ```go package main import ( "context" "log" "os" "github.com/bytedance/sonic" "github.com/cloudwego/eino-ext/components/model/agenticopenai" "github.com/cloudwego/eino/schema" openaischema "github.com/cloudwego/eino/schema/openai" "github.com/eino-contrib/jsonschema" "github.com/openai/openai-go/v3/responses" "github.com/wk8/go-ordered-map/v2" ) func main() { ctx := context.Background() am, err := agenticopenai.New(ctx, &agenticopenai.Config{ BaseURL: "https://api.agenticopenai.com/v1", Model: os.Getenv("OPENAI_MODEL_ID"), APIKey: os.Getenv("OPENAI_API_KEY"), Reasoning: &responses.ReasoningParam{ Effort: responses.ReasoningEffortLow, Summary: responses.ReasoningSummaryDetailed, }, }) if err != nil { log.Fatalf("failed to create agentic model, err: %v", err) } input := []*schema.AgenticMessage{ schema.UserAgenticMessage("what is the weather like in Beijing"), } am_, err := am.WithTools([]*schema.ToolInfo{ { Name: "get_weather", Desc: "get the weather in a city", ParamsOneOf: schema.NewParamsOneOfByJSONSchema(&jsonschema.Schema{ Type: "object", Properties: orderedmap.New[string, *jsonschema.Schema]( orderedmap.WithInitialData( orderedmap.Pair[string, *jsonschema.Schema]{ Key: "city", Value: &jsonschema.Schema{ Type: "string", Description: "the city to get the weather", }, }, ), ), Required: []string{"city"}, }), }, }) if err != nil { log.Fatalf("failed to create agentic model with tools, err: %v", err) } msg, err := am_.Generate(ctx, input) if err != nil { log.Fatalf("failed to generate, err: %v", err) } meta := msg.ResponseMeta.Extension.(*openaischema.ResponseMetaExtension) log.Printf("request_id: %s\n", meta.ID) respBody, _ := sonic.MarshalIndent(msg, " ", " ") log.Printf(" body: %s\n", string(respBody)) } ``` -------------------------------- ### Example UserInputFile Initialization Source: https://cloudwego.cn/docs/eino/core_modules/components/agentic_chat_model_guide Example of how to initialize a UserInputFile object with URL, Name, and MIME type. ```go fileInput := &schema.UserInputFile{ URL: "https://example.com/report.pdf", Name: "report.pdf", MIMEType: "application/pdf", } ``` -------------------------------- ### Example AssistantGenAudio Initialization Source: https://cloudwego.cn/docs/eino/core_modules/components/agentic_chat_model_guide Example of initializing an AssistantGenAudio object with a URL and MIME type. ```go audioGen := &schema.AssistantGenAudio{ URL: "https://api.example.com/generated/audio123.wav", MIMEType: "audio/wav", } ``` -------------------------------- ### Run Chat with Eino Quickstart Source: https://cloudwego.cn/docs/eino/quick_start/chapter_01_chatmodel_and_message Execute the quickstart application with a query. The application will use the configured ChatModel to respond. ```bash go run ./cmd/ch01 -- "Explain in one sentence what problem Eino’s Component design solves." ``` -------------------------------- ### Install Agentkit Backend Source: https://cloudwego.cn/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/filesystem_backend/backend_ark_agentkit_sandbox Use 'go get' to install the agentkit backend package. Ensure your eino version is compatible. ```go go get github.com/cloudwego/eino-ext/adk/backend/agentkit ``` -------------------------------- ### Install Eino and OpenAI Model Source: https://cloudwego.cn/docs/eino/core_modules/flow_integration_components/react_agent_manual Installs the Eino framework 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 ``` -------------------------------- ### Example UserInputVideo Initialization Source: https://cloudwego.cn/docs/eino/core_modules/components/agentic_chat_model_guide Example of how to initialize a UserInputVideo object with a URL and MIME type. ```go videoInput := &schema.UserInputVideo{ URL: "https://example.com/demo.mp4", MIMEType: "video/mp4", } ``` -------------------------------- ### OnStart Callback Example Source: https://cloudwego.cn/docs/eino/core_modules/eino_adk/adk_agent_callback Illustrates the OnStart callback during agent execution. ```go OnStart ``` -------------------------------- ### Install Eino Ark Model Source: https://cloudwego.cn/docs/eino/core_modules/flow_integration_components/react_agent_manual Installs the Eino framework and the Ark model component using go get. ```go go get github.com/cloudwego/eino-ext/components/model/ark@latest ``` -------------------------------- ### Complete Retriever Implementation Example Source: https://cloudwego.cn/docs/eino/core_modules/components/retriever_guide This example demonstrates a full implementation of a custom retriever, including initialization, option handling, and integration with the callback manager for start, error, and end events. It shows how to generate query vectors using an embedder. ```go type MyRetriever struct { embedder embedding.Embedder index string topK int } func NewMyRetriever(config *MyRetrieverConfig) (*MyRetriever, error) { return &MyRetriever{ embedder: config.Embedder, index: config.Index, topK: config.DefaultTopK, }, nil } func (r *MyRetriever) Retrieve(ctx context.Context, query string, opts ...retriever.Option) ([]*schema.Document, error) { // 1. Handle options options := &retriever.Options{ Index: &r.index, TopK: &r.topK, Embedding: r.embedder, } options = retriever.GetCommonOptions(options, opts...) // 2. Get callback manager cm := callbacks.ManagerFromContext(ctx) // 3. Callback before retrieval starts ctx = cm.OnStart(ctx, info, &retriever.CallbackInput{ Query: query, TopK: *options.TopK, }) // 4. Execute retrieval logic docs, err := r.doRetrieve(ctx, query, options) // 5. Handle error and completion callbacks if err != nil { ctx = cm.OnError(ctx, info, err) return nil, err } ctx = cm.OnEnd(ctx, info, &retriever.CallbackOutput{ Docs: docs, }) return docs, nil } func (r *MyRetriever) doRetrieve(ctx context.Context, query string, opts *retriever.Options) ([]*schema.Document, error) { // 1. If Embedding is set, generate vector representation of the query (note common option logic handling) var queryVector []float64 if opts.Embedding != nil { vectors, err := opts.Embedding.EmbedStrings(ctx, []string{query}) if err != nil { return nil, err } queryVector = vectors[0] } // 2. Other logic return docs, nil } ``` -------------------------------- ### Example Reasoning Initialization Source: https://cloudwego.cn/docs/eino/core_modules/components/agentic_chat_model_guide Demonstrates how to initialize a Reasoning struct with text and a signature. ```go reasoning := &schema.Reasoning{ Text: "The user now needs me to solve...", Signature: "asjkhvipausdgy23oadlfdsf" } ``` -------------------------------- ### Complete Indexer Implementation Example Source: https://cloudwego.cn/docs/eino/core_modules/components/indexer_guide A full example of an Indexer implementation, including NewMyIndexer constructor, Store method with option and callback handling, and doStore for storage logic. ```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 } ``` -------------------------------- ### Quick Start: Using AgenticModel Source: https://cloudwego.cn/docs/eino/ecosystem_integration/chat_model/agentic_model_ark This example demonstrates how to initialize and use the AgenticModel with Volcengine Ark. Ensure ARK_API_KEY and ARK_MODEL_ID environment variables are set. ```go package main import ( "context" "log" "os" "github.com/bytedance/sonic" "github.com/cloudwego/eino-ext/components/model/agenticark" "github.com/cloudwego/eino/schema" ) func main() { ctx := context.Background() // Get ARK_API_KEY and ARK_MODEL_ID: https://www.volcengine.com/docs/82379/1399008 am, err := agenticark.New(ctx, &agenticark.Config{ Model: os.Getenv("ARK_MODEL_ID"), APIKey: os.Getenv("ARK_API_KEY"), }) if err != nil { log.Fatalf("failed to create agentic model, err: %v", err) } input := []*schema.AgenticMessage{ schema.UserAgenticMessage("what is the weather like in Beijing"), } msg, err := am.Generate(ctx, input) if err != nil { log.Fatalf("failed to generate, err: %v", err) } meta := msg.ResponseMeta.Extension.(*agenticark.ResponseMetaExtension) log.Printf("request_id: %s ", meta.ID) respBody, _ := sonic.MarshalIndent(msg, " ", " ") log.Printf(" body: %s ", string(respBody)) } ``` -------------------------------- ### Example MCPToolApprovalResponse Source: https://cloudwego.cn/docs/eino/core_modules/components/agentic_chat_model_guide An example of creating an MCPToolApprovalResponse instance, setting the approval status and reason. ```go approvalResp := &schema.MCPToolApprovalResponse{ ApprovalRequestID: "approval_789", Approve: true, Reason: "Confirmed deletion of inactive users", } ``` -------------------------------- ### Minimal AgentsMD Middleware Example Source: https://cloudwego.cn/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/middleware_agentsmd Demonstrates the minimal setup for creating and attaching the agentsmd middleware. Requires a file reading backend and specifies the Agents.md files to load. ```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. Attach the middleware to the agent // agent := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{ // Middlewares: []adk.ChatModelAgentMiddleware{mw}, // }) _ = mw fmt.Println("agentsmd middleware created successfully") } ``` -------------------------------- ### File Loader with Callbacks Source: https://cloudwego.cn/docs/eino/core_modules/components/document_loader_guide Example of using the File Loader with custom callback handlers for start and end events during the loading process. ```go import ( "github.com/cloudwego/eino/callbacks" "github.com/cloudwego/eino/components/document" "github.com/cloudwego/eino/compose" "github.com/cloudwego/eino/schema" callbacksHelper "github.com/cloudwego/eino/utils/callbacks" "github.com/cloudwego/eino-ext/components/document/loader/file" ) // Create callback handler handler := &callbacksHelper.LoaderCallbackHandler{ OnStart: func(ctx context.Context, info *callbacks.RunInfo, input *document.LoaderCallbackInput) context.Context { log.Printf("start loading docs...: %s\n", input.Source.URI) return ctx }, OnEnd: func(ctx context.Context, info *callbacks.RunInfo, output *document.LoaderCallbackOutput) context.Context { log.Printf("complete loading docs, total loaded docs: %d\n", len(output.Docs)) return ctx }, // OnError } // Use callback handler helper := callbacksHelper.NewHandlerHelper(). Loader(handler). Handler() chain := compose.NewChain[document.Source, []*schema.Document]() chain.AppendLoader(loader) // Use at runtime run, _ := chain.Compile(ctx) outDocs, _ := run.Invoke(ctx, document.Source{ URI: filePath, }, compose.WithCallbacks(helper)) log.Printf("doc content: %v", outDocs[0].Content) ``` -------------------------------- ### Example MCPToolApprovalRequest Initialization Source: https://cloudwego.cn/docs/eino/core_modules/components/agentic_chat_model_guide Example of initializing an MCPToolApprovalRequest. The Arguments field should be a JSON string representing the tool's parameters. ```go approvalReq := &schema.MCPToolApprovalRequest{ ID: "approval_20260112_001", Name: "delete_records", Arguments: `{"table": "users", "condition": "inactive=true", "estimated_count": 150}`, ServerLabel: "database-server", } ``` -------------------------------- ### Example AssistantGenImage Initialization Source: https://cloudwego.cn/docs/eino/core_modules/components/agentic_chat_model_guide Example of initializing an AssistantGenImage object with a URL and MIME type. ```go imageGen := &schema.AssistantGenImage{ URL: "https://api.example.com/generated/image123.png", MIMEType: "image/png", } ``` -------------------------------- ### Example AssistantGenText Creation Source: https://cloudwego.cn/docs/eino/core_modules/components/agentic_chat_model_guide Example of creating an AssistantGenText object with generated text and custom extensions. ```go textGen := &schema.AssistantGenText{ Text: "Based on your requirements, I suggest the following approach...", Extension: &AssistantGenTextExtension{ Annotations: []*TextAnnotation{annotation}, }, } ``` -------------------------------- ### Example MCPListToolsResult Initialization Source: https://cloudwego.cn/docs/eino/core_modules/components/agentic_chat_model_guide Example of initializing MCPListToolsResult with a list of available tools. The InputSchema should be a valid JSON schema. ```go toolsList := &schema.MCPListToolsResult{ ServerLabel: "database-server", Tools: []*schema.MCPListToolsItem{ { Name: "execute_query", Description: "Execute SQL query", InputSchema: &jsonschema.Schema{...}, }, { Name: "create_table", Description: "Create database table", InputSchema: &jsonschema.Schema{...}, }, }, } ``` -------------------------------- ### Complete Eino Graph Example with State Management Source: https://cloudwego.cn/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 defining the graph's execution flow. ```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 } ``` -------------------------------- ### Server Tool Example with Eino Source: https://cloudwego.cn/docs/eino/ecosystem_integration/chat_model/agentic_model_ark This Go code snippet demonstrates how to use server tools, such as web search, with the Eino framework. It requires setting ARK_API_KEY and ARK_MODEL_ID environment variables. The example streams a response and processes server tool calls. ```go package main import ( "context" "errors" "io" "log" "os" "github.com/bytedance/sonic" "github.com/cloudwego/eino-ext/components/model/agenticark" "github.com/cloudwego/eino/components/model" "github.com/cloudwego/eino/schema" "github.com/volcengine/volcengine-go-sdk/service/arkruntime/model/responses" ) func main() { ctx := context.Background() // Get ARK_API_KEY and ARK_MODEL_ID: https://www.volcengine.com/docs/82379/1399008 am, err := agenticark.New(ctx, &agenticark.Config{ Model: os.Getenv("ARK_MODEL_ID"), APIKey: os.Getenv("ARK_API_KEY"), }) if err != nil { log.Fatalf("failed to create agentic model, err=%v", err) } serverTools := []*agenticark.ServerToolConfig{ { WebSearch: &responses.ToolWebSearch{ Type: responses.ToolType_web_search, }, }, } allowedTools := []*schema.AllowedTool{ { ServerTool: &schema.AllowedServerTool{ Name: string(agenticark.ServerToolNameWebSearch), }, }, } opts := []model.Option{ agenticark.WithServerTools(serverTools), model.WithAgenticToolChoice(&schema.AgenticToolChoice{ Type: schema.ToolChoiceForced, Forced: &schema.AgenticForcedToolChoice{ Tools: allowedTools, }, }), agenticark.WithThinking(&responses.ResponsesThinking{ Type: responses.ThinkingType_disabled.Enum(), }), } input := []*schema.AgenticMessage{ schema.UserAgenticMessage("what's the weather like in Beijing today"), } resp, err := am.Stream(ctx, input, opts...) if err != nil { log.Fatalf("failed to stream, err: %v", err) } var msgs []*schema.AgenticMessage for { msg, err := resp.Recv() if err != nil { if errors.Is(err, io.EOF) { break } log.Fatalf("failed to receive stream response, err: %v", err) } msgs = append(msgs, msg) } concatenated, err := schema.ConcatAgenticMessages(msgs) if err != nil { log.Fatalf("failed to concat agentic messages, err: %v", err) } meta := concatenated.ResponseMeta.Extension.(*agenticark.ResponseMetaExtension) for _, block := range concatenated.ContentBlocks { if block.ServerToolCall == nil { continue } serverToolArgs := block.ServerToolCall.Arguments.(*agenticark.ServerToolCallArguments) args, _ := sonic.MarshalIndent(serverToolArgs, " ", " ") log.Printf("server_tool_args: %s\n", string(args)) } log.Printf("request_id: %s\n", meta.ID) respBody, _ := sonic.MarshalIndent(concatenated, " ", " ") log.Printf(" body: %s\n", string(respBody)) } ``` -------------------------------- ### InvokableApprovableTool Example Source: https://cloudwego.cn/docs/eino/core_modules/chain_and_graph_orchestration/checkpoint_interrupt This example demonstrates how resume data is used within an InvokableApprovableTool. It handles initial invocation, interruption, and resumption with or without approval data. ```go func (i InvokableApprovableTool) InvokableRun(ctx context.Context, argumentsInJSON string, opts ...tool.Option) (string, error) { toolInfo, err := i.Info(ctx) if err != nil { return "", err } wasInterrupted, _, storedArguments := compose.GetInterruptState[string](ctx) if !wasInterrupted { // initial invocation, interrupt and wait for approval return "", compose.StatefulInterrupt(ctx, &ApprovalInfo{ ToolName: toolInfo.Name, ArgumentsInJSON: argumentsInJSON, ToolCallID: compose.GetToolCallID(ctx), }, argumentsInJSON) } isResumeTarget, hasData, data := compose.GetResumeContext[*ApprovalResult](ctx) if !isResumeTarget { // was interrupted but not explicitly resumed, reinterrupt and wait for approval again return "", compose.StatefulInterrupt(ctx, &ApprovalInfo{ ToolName: toolInfo.Name, ArgumentsInJSON: storedArguments, ToolCallID: compose.GetToolCallID(ctx), }, storedArguments) } if !hasData { return "", fmt.Errorf("tool '%s' resumed with no data", toolInfo.Name) } if data.Approved { return i.InvokableTool.InvokableRun(ctx, storedArguments, opts...) } if data.DisapproveReason != nil { return fmt.Sprintf("tool '%s' disapproved, reason: %s", toolInfo.Name, *data.DisapproveReason), nil } return fmt.Sprintf("tool '%s' disapproved", toolInfo.Name), nil } ``` -------------------------------- ### Eino Debugging Main Process Example Source: https://cloudwego.cn/docs/eino/core_modules/devops/visual_debug_plugin_guide Example of a main function that initializes the Eino debug service, registers orchestration artifacts, and keeps the process alive to allow debugging. ```go func main() { ctx := context.Background() // Init eino devops server err := devops.Init(ctx) if err != nil { logs.Errorf("[eino dev] init failed, err=%v", err) return } // Register chain, graph and state_graph for demo use chain.RegisterSimpleChain(ctx) graph.RegisterSimpleGraph(ctx) graph.RegisterSimpleStateGraph(ctx) // Blocking process exits sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) <-sigs // Exit logs.Infof("[eino dev] shutting down\n") } ``` -------------------------------- ### Example: Chain with Selective Handler Source: https://cloudwego.cn/docs/eino/core_modules/chain_and_graph_orchestration/callback_manual Demonstrates how to create a chain of operations and compile it with a custom selective handler. This example shows how to mount handlers and configure the chain compilation. ```go // Combination example: outer call wants to trigger, specific handler filters out inner ChatModel through RunInfo func Example(cm model.BaseChatModel) (compose.Runnable[string, string], error) { handler := newSelectiveHandler() chain := compose.NewChain[string, string](). AppendLambda(OuterLambdaCallsChatModel(cm)) // Will ReuseHandlers + RunInfo internally return chain.Compile( context.Background(), // Mount handler (can also combine with global handlers) compose.WithCallbacks(handler), ) } ``` -------------------------------- ### Complete Custom Transformer Implementation Example Source: https://cloudwego.cn/docs/eino/core_modules/components/document_transformer_guide Provides a full example of a custom Transformer component, including its constructor, the Transform method which handles options and callbacks, and a placeholder for the core transformation logic. ```go type MyTransformer struct { chunkSize int overlap int minChunkLength int } func NewMyTransformer(config *MyTransformerConfig) (*MyTransformer, error) { return &MyTransformer{ chunkSize: config.DefaultChunkSize, overlap: config.DefaultOverlap, minChunkLength: config.DefaultMinChunkLength, }, nil } func (t *MyTransformer) Transform(ctx context.Context, src []*schema.Document, opts ...document.TransformerOption) ([]*schema.Document, error) { // 1. Handle Options options := &MyTransformerOptions{ ChunkSize: t.chunkSize, Overlap: t.overlap, MinChunkLength: t.minChunkLength, } options = document.GetTransformerImplSpecificOptions(options, opts...) // 2. Callback before transformation starts ctx = callbacks.OnStart(ctx, info, &document.TransformerCallbackInput{ Input: src, }) // 3. Execute transformation logic docs, err := t.doTransform(ctx, src, options) // 4. Handle errors and completion callback if err != nil { ctx = callbacks.OnError(ctx, info, err) return nil, err } ctx = callbacks.OnEnd(ctx, info, &document.TransformerCallbackOutput{ Output: docs, }) return docs, nil } func (t *MyTransformer) doTransform(ctx context.Context, src []*schema.Document, opts *MyTransformerOptions) ([]*schema.Document, error) { // Implement document transformation logic return docs, nil } ``` -------------------------------- ### Clone eino-examples Repository Source: https://cloudwego.cn/docs/eino/core_modules/devops/visual_debug_plugin_guide Clone the eino-examples repository to get started with Eino debugging examples. Use either HTTPS or SSH. ```bash git clone https://github.com/cloudwego/eino-examples.git # or git clone git@github.com:cloudwego/eino-examples.git ``` -------------------------------- ### Install AgenticOpenAI Component Source: https://cloudwego.cn/docs/eino/ecosystem_integration/chat_model/agentic_model_openai Use 'go get' to install the latest version of the agenticopenai component for your Go project. ```bash go get github.com/cloudwego/eino-ext/components/model/agenticopenai@latest ``` -------------------------------- ### Server Tool Example with Web Search Source: https://cloudwego.cn/docs/eino/ecosystem_integration/chat_model/agentic_model_openai This Go code demonstrates how to initialize an agentic OpenAI client, configure server tools (specifically web search), set allowed tools, and stream a response from the model. It then processes the response to extract and log server tool arguments and results. ```go package main import ( "context" "errors" "io" "log" "os" "github.com/bytedance/sonic" "github.com/cloudwego/eino-ext/components/model/agenticopenai" "github.com/cloudwego/eino/components/model" "github.com/cloudwego/eino/schema" "github.com/openai/openai-go/v3/responses" ) func main() { ctx := context.Background() am, err := agenticopenai.New(ctx, &agenticopenai.Config{ BaseURL: "https://api.agenticopenai.com/v1", Model: os.Getenv("OPENAI_MODEL_ID"), APIKey: os.Getenv("OPENAI_API_KEY"), Reasoning: &responses.ReasoningParam{ Effort: responses.ReasoningEffortLow, Summary: responses.ReasoningSummaryDetailed, }, Include: []responses.ResponseIncludable{ responses.ResponseIncludableWebSearchCallActionSources, }, }) if err != nil { log.Fatalf("failed to create agentic model, err=%v", err) } serverTools := []*agenticopenai.ServerToolConfig{ { WebSearch: &responses.WebSearchToolParam{ Type: responses.WebSearchToolTypeWebSearch, }, }, } allowedTools := []*schema.AllowedTool{ { ServerTool: &schema.AllowedServerTool{ Name: string(agenticopenai.ServerToolNameWebSearch), }, }, } opts := []model.Option{ model.WithAgenticToolChoice(&schema.AgenticToolChoice{ Forced: &schema.AgenticForcedToolChoice{ Tools: allowedTools, }, }), agenticopenai.WithServerTools(serverTools), } input := []*schema.AgenticMessage{ schema.UserAgenticMessage("what's cloudwego/eino"), } resp, err := am.Stream(ctx, input, opts...) if err != nil { log.Fatalf("failed to stream, err: %v", err) } var msgs []*schema.AgenticMessage for { msg, err := resp.Recv() if err != nil { if errors.Is(err, io.EOF) { break } log.Fatalf("failed to receive stream response, err: %v", err) } msgs = append(msgs, msg) } concatenated, err := schema.ConcatAgenticMessages(msgs) if err != nil { log.Fatalf("failed to concat agentic messages, err: %v", err) } for _, block := range concatenated.ContentBlocks { if block.ServerToolCall != nil { serverToolArgs := block.ServerToolCall.Arguments.(*agenticopenai.ServerToolCallArguments) args, _ := sonic.MarshalIndent(serverToolArgs, " ", " ") log.Printf("server_tool_args: %s\n", string(args)) } if block.ServerToolResult != nil { result := block.ServerToolResult.Result.(*agenticopenai.ServerToolResult) resultJSON, _ := sonic.MarshalIndent(result, " ", " ") log.Printf("server_tool_result: %s\n", string(resultJSON)) } } meta := concatenated.ResponseMeta.OpenAIExtension log.Printf("request_id: %s\n", meta.ID) respBody, _ := sonic.MarshalIndent(concatenated, " ", " ") log.Printf(" body: %s\n", string(respBody)) } ``` -------------------------------- ### Install Eino ADK Source: https://cloudwego.cn/docs/eino/core_modules/eino_adk/agent_quickstart Use 'go get' to install or upgrade the Eino ADK package to the latest stable version. ```go // stable >= eino@v0.5.0 go get github.com/cloudwego/eino@latest ``` -------------------------------- ### Basic Local Backend Usage Source: https://cloudwego.cn/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 creating a new local backend instance and performing basic file read/write operations. 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) } // 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) } ``` -------------------------------- ### Agent Generate Call Source: https://cloudwego.cn/docs/eino/core_modules/flow_integration_components/react_agent_manual Example of how to use the `Generate` method of an Eino Agent to get a response. Ensure the agent is initialized with `react.NewAgent(...)`. ```go agent, _ := react.NewAgent(...) var outMessage *schema.Message outMessage, err = agent.Generate(ctx, []*schema.Message{ schema.UserMessage("写一个 golang 的 hello world 程序"), }) ``` -------------------------------- ### Run Eino Agent Example Source: https://cloudwego.cn/docs/eino/overview/bytedance_eino_practice Execute the Eino agent sample. Load environment variables and run the Go program from the eino_assistant directory. ```bash cd eino-examples/eino_assistant # Load env vars (model info, tracing platform info) source .env # Run from eino_assistant to use the embedded data directory go run cmd/einoagent/*.go ``` -------------------------------- ### Install Eino ADK using Go Modules Source: https://cloudwego.cn/docs/eino/overview/eino_adk0_1 Command to add the Eino ADK library to your Go project dependencies using the go get command. ```bash go get github.com/cloudwego/eino@latest ``` -------------------------------- ### Example UserInputAudio Initialization Source: https://cloudwego.cn/docs/eino/core_modules/components/agentic_chat_model_guide Shows how to initialize a UserInputAudio struct using a URL and specifying the MIME type. ```go audioInput := &schema.UserInputAudio{ URL: "https://example.com/voice.wav", MIMEType: "audio/wav", } ``` -------------------------------- ### Create AddUser Tool using NewTool Source: https://cloudwego.cn/docs/eino/core_modules/components/tools_node_guide/how_to_create_a_tool This example demonstrates creating an 'add_user' tool by wrapping the AddUser function using utils.NewTool. It defines the tool's metadata, including its name, description, and parameter schema with type constraints and required fields. ```go import ( "github.com/cloudwego/eino/components/tool" "github.com/cloudwego/eino/components/tool/utils" "github.com/cloudwego/eino/schema" ) type User struct { Name string `json:"name"` Age int `json:"age"` Gender string `json:"gender"` } type Result struct { Msg string `json:"msg"` } func AddUser(ctx context.Context, user *User) (*Result, error) { // some logic } func createTool() tool.InvokableTool { addUserTool := utils.NewTool(&schema.ToolInfo{ Name: "add_user", Desc: "add user", ParamsOneOf: schema.NewParamsOneOfByParams( map[string]*schema.ParameterInfo{ "name": &schema.ParameterInfo{ Type: schema.String, Required: true, }, "age": &schema.ParameterInfo{ Type: schema.Integer, }, "gender": &schema.ParameterInfo{ Type: schema.String, Enum: []string{"male", "female"}, }, }, ), }, AddUser) return addUserTool } ``` -------------------------------- ### Prompt for Skill Tool Verification Source: https://cloudwego.cn/docs/eino/quick_start/chapter_09_skill_console This prompt is used to verify that the skill middleware is correctly configured and that skills are discoverable. It asks the agent to use the 'eino-guide' skill to explain the entry point for getting started. ```plaintext Use the skill tool with skill="eino-guide" and tell me what the entry point is for getting started. ``` -------------------------------- ### Basic Agentkit Sandbox Backend Usage Source: https://cloudwego.cn/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/filesystem_backend/backend_ark_agentkit_sandbox Demonstrates initializing the sandbox backend and performing basic file operations like writing and reading. Ensure environment variables are set. ```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) } // Write file err = backend.Write(ctx, &filesystem.WriteRequest{ FilePath: "/home/gem/hello.txt", Content: "Hello, Sandbox!", }) // Read file fContent, err := backend.Read(ctx, &filesystem.ReadRequest{ FilePath: "/home/gem/hello.txt", }) fmt.Println(fContent.Content) } ``` -------------------------------- ### Run Knowledge Indexing Example Source: https://cloudwego.cn/docs/eino/overview/bytedance_eino_practice Execute the knowledge indexing sample. Ensure environment variables are loaded and navigate to the correct directory before running. ```bash cd xxx/eino-examples/quickstart/eino_assistant # Load env vars (model info, tracing platform info) source .env # The sample Markdown lives in cmd/knowledgeindexing/eino-docs. # Because the code uses the relative path "eino-docs", run from cmd/knowledgeindexing cd cmd/knowledgeindexing go run main.go ``` -------------------------------- ### Eino Tool Callback Handler Example in Go Source: https://cloudwego.cn/docs/eino/core_modules/components/agentic_tools_node_guide Set up a callback handler to manage tool execution lifecycle events such as start, end, and streaming output. This handler can be used to log information or process results. ```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/tool" ) // Create callback handler handler := &callbackHelper.ToolCallbackHandler{ OnStart: func(ctx context.Context, info *callbacks.RunInfo, input *tool.CallbackInput) context.Context { fmt.Printf("Starting tool execution, arguments: %s\n", input.ArgumentsInJSON) return ctx }, OnEnd: func(ctx context.Context, info *callbacks.RunInfo, output *tool.CallbackOutput) context.Context { fmt.Printf("Tool execution completed, result: %s\n", output.Response) return ctx }, OnEndWithStreamOutput: func(ctx context.Context, info *callbacks.RunInfo, output *schema.StreamReader[*tool.CallbackOutput]) context.Context { fmt.Println("Tool starting streaming output") go func() { defer output.Close() for { chunk, err := output.Recv() if errors.Is(err, io.EOF) { return } if err != nil { return } fmt.Printf("Received streaming output: %s\n", chunk.Response) } }() return ctx }, } // Use callback handler helper := callbackHelper.NewHandlerHelper(). Tool(handler). Handler() /*** compose a chain * chain := NewChain * chain.appendxxx(). * appendxxx(). * ... */ // Use at runtime runnable, err := chain.Compile() if err != nil { return err } result, err := runnable.Invoke(ctx, input, compose.WithCallbacks(helper)) ``` -------------------------------- ### Initialize ToolSearch Middleware and Agent Source: https://cloudwego.cn/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/middleware_toolsearch Demonstrates how to initialize the ToolSearch middleware with a list of dynamic tools and then create an agent that uses this middleware. ```go middleware, err := toolsearch.New(ctx, &toolsearch.Config{ DynamicTools: []tool.BaseTool{ weatherTool, stockTool, currencyTool, // ... many tools }, }) if err != nil { return err } agent, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{ Model: myModel, Handlers: []adk.ChatModelAgentMiddleware{middleware}, }) ``` -------------------------------- ### Create Local Filesystem Backend and Skill Middleware Source: https://cloudwego.cn/docs/eino/core_modules/eino_adk/eino_adk_chatmodelagentmiddleware/middleware_skill Initializes a local filesystem backend and creates a Skill middleware instance. Ensure the 'skillsDir' variable is correctly defined before use. ```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, }) ``` -------------------------------- ### OpenSearch 2 Indexer Setup and Usage Source: https://cloudwego.cn/docs/eino/core_modules/components/indexer_guide Shows how to initialize an OpenSearch 2 indexer, define document field mapping with embedding keys, and index documents. Requires OpenSearch client configuration and an embedding component. ```go package main import ( "github.com/cloudwego/eino/schema" opensearch "github.com/opensearch-project/opensearch-go/v2" "github.com/cloudwego/eino-ext/components/indexer/opensearch2" ) client, err := opensearch.NewClient(opensearch.Config{ Addresses: []string{"http://localhost:9200"}, Username: username, Password: password, }) // Create opensearch indexer component indexer, _ := opensearch2.NewIndexer(ctx, &opensearch2.IndexerConfig{ Client: client, Index: "your_index_name", BatchSize: 10, DocumentToFields: func(ctx context.Context, doc *schema.Document) (map[string]opensearch2.FieldValue, error) { return map[string]opensearch2.FieldValue{ "content": { Value: doc.Content, EmbedKey: "content_vector", }, }, nil }, Embedding: emb, }) // Index documents docs := []*schema.Document{ { ID: "doc1", Content: "EINO is a framework for building AI applications", }, } ids, err := indexer.Store(ctx, docs) ``` -------------------------------- ### Example UserInputText Initialization Source: https://cloudwego.cn/docs/eino/core_modules/components/agentic_chat_model_guide Shows how to create a UserInputText instance. Convenience functions are available for creating system, user, and developer messages. ```go textInput := &schema.UserInputText{ Text: "Please help me analyze the performance bottleneck of this code", } // Or use convenience functions to create messages textInput := schema.UserAgenticMessage("Please help me analyze the performance bottleneck of this code") textInput := schema.SystemAgenticMessage("You are an intelligent assistant") textInput := schema.DeveloperAgenticMessage("You are an intelligent assistant") ``` -------------------------------- ### Initialize and Use File Loader Source: https://cloudwego.cn/docs/eino/core_modules/components/document_loader_guide Demonstrates standalone usage of the File Loader, including initialization and loading a document by its file path. ```go import ( "github.com/cloudwego/eino/components/document" "github.com/cloudwego/eino/components/document/loader/file" ) // Initialize loader (using file loader as example) loader, _ := file.NewFileLoader(ctx, &file.FileLoaderConfig{ // Configuration parameters UseNameAsID: true, }) // Load document filePath := "../../testdata/test.md" docs, _ := loader.Load(ctx, document.Source{ URI: filePath, }) log.Printf("doc content: %v", docs[0].Content) ```