
Eino Component
- 201 installs
- 785 repo stars
- Updated August 3, 2026
- cloudwego/eino-ext
Select and configure AI components for agent and RAG system architectures with multi-provider support.
About
Guides selection, configuration, and usage of Eino components including LLM models, embeddings, retrievers, indexers, and tool integrations. Use when choosing and wiring components for RAG pipelines or agent workflows.
- Component selection across ChatModel, AgenticModel, Embedding, Retriever, Indexer, Tools
- Multi-provider support (OpenAI, Claude, Gemini, Ollama, Milvus, Elasticsearch, MCP tools)
Eino Component by the numbers
- 201 all-time installs (skills.sh)
- Ranked #2,858 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cloudwego/eino-ext --skill eino-componentAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 201 |
|---|---|
| repo stars | ★ 785 |
| Last updated | August 3, 2026 |
| Repository | cloudwego/eino-ext ↗ |
What it does
Select and configure AI components for agent and RAG system architectures with multi-provider support.
Files
Eino Component Guide
Component Selection Guide
ChatModel -- LLM inference (classic Message path)
| Provider | Package | Notes |
|---|---|---|
| OpenAI | model/openai | Also supports Azure via ByAzure: true |
| Claude | model/claude | Also supports AWS Bedrock via ByBedrock: true |
| Gemini | model/gemini | Requires genai.Client |
| Ark (Volcengine) | model/ark | Doubao models |
| Ollama | model/ollama | Local models |
| DeepSeek | model/deepseek | Reasoning support |
| Qwen | model/qwen | Alibaba DashScope API |
| Qianfan | model/qianfan | Baidu ERNIE models |
| OpenRouter | model/openrouter | Multi-provider routing |
AgenticModel -- LLM inference (AgenticMessage path)
AgenticModel operates on *schema.AgenticMessage with block-based content (reasoning, text, images, audio, video, tool calls/results). Tools are always passed at call time via model.WithTools option (no WithTools method).
| Provider | Package | Notes |
|---|---|---|
| OpenAI | model/agenticopenai | GPT-4o, o1, o3 series |
| Gemini | model/agenticgemini | Gemini 2.x models |
| DeepSeek | model/agenticdeepseek | DeepSeek-R1 with reasoning |
| Ark (Volcengine) | model/agenticark | Doubao models (agentic path) |
| Qwen | model/agenticqwen | Qwen series via DashScope |
Detailed configuration references:
reference/model/agenticopenai.mdreference/model/agenticgemini.mdreference/model/agenticdeepseek.mdreference/model/agenticark.mdreference/model/agenticqwen.md
Embedding -- text to vector
| Provider | Package | Notes |
|---|---|---|
| OpenAI | embedding/openai | text-embedding-3-small/large, ada-002 |
| Ark | embedding/ark | Volcengine embedding models |
| Gemini | embedding/gemini | Google embedding models |
| DashScope | embedding/dashscope | Alibaba embedding |
| Ollama | embedding/ollama | Local embedding models |
| Qianfan | embedding/qianfan | Baidu embedding |
Retriever -- vector/keyword search
| Backend | Package | Notes |
|---|---|---|
| Redis | retriever/redis | KNN and range vector search |
| Milvus 2.x | retriever/milvus2 | Dense + sparse hybrid, BM25 |
| Elasticsearch 8 | retriever/es8 | Approximate vector search |
| Qdrant | retriever/qdrant | Vector similarity search |
Indexer -- store documents with vectors
| Backend | Package |
|---|---|
| Redis | indexer/redis |
| Milvus 2.x | indexer/milvus2 |
| Elasticsearch 8 | indexer/es8 |
| Qdrant | indexer/qdrant |
Tools -- model-callable functions
| Tool | Package | Notes |
|---|---|---|
| MCP | tool/mcp | Model Context Protocol tools |
| Google Search | tool/googlesearch | Custom Search JSON API |
| DuckDuckGo | tool/duckduckgo | Web search (use v2) |
| Bing Search | tool/bingsearch | Bing Web Search API |
| HTTP Request | tool/httprequest | Generic HTTP calls |
| Command Line | tool/commandline | Shell command execution |
| Browser Use | tool/browseruse | Browser automation |
Interface Quick Reference
// BaseModel (generic)
type BaseModel[M any] interface {
Generate(ctx context.Context, input []M, opts ...Option) (M, error)
Stream(ctx context.Context, input []M, opts ...Option) (*schema.StreamReader[M], error)
}
// Type aliases
type BaseChatModel = BaseModel[*schema.Message] // classic path
type AgenticModel = BaseModel[*schema.AgenticMessage] // agentic path
// ToolCallingChatModel (classic path, adds WithTools)
type ToolCallingChatModel interface {
BaseChatModel
WithTools(tools []*schema.ToolInfo) (ToolCallingChatModel, error)
}
// Embedding
type Embedder interface {
EmbedStrings(ctx context.Context, texts []string, opts ...Option) ([][]float64, error)
}
// Retriever
type Retriever interface {
Retrieve(ctx context.Context, query string, opts ...Option) ([]*schema.Document, error)
}
// Indexer
type Indexer interface {
Store(ctx context.Context, docs []*schema.Document, opts ...Option) (ids []string, err error)
}
// Document
type Loader interface {
Load(ctx context.Context, src Source, opts ...LoaderOption) ([]*schema.Document, error)
}
type Transformer interface {
Transform(ctx context.Context, src []*schema.Document, opts ...TransformerOption) ([]*schema.Document, error)
}
// Tool
type BaseTool interface {
Info(ctx context.Context) (*schema.ToolInfo, error)
}
type InvokableTool interface {
BaseTool
InvokableRun(ctx context.Context, argumentsInJSON string, opts ...Option) (string, error)
}
// Prompt
type ChatTemplate interface {
Format(ctx context.Context, vs map[string]any, opts ...Option) ([]*schema.Message, error)
}Installation
go get github.com/cloudwego/eino-ext/components/{type}/{impl}@latest
# Examples:
go get github.com/cloudwego/eino-ext/components/model/openai@latest
go get github.com/cloudwego/eino-ext/components/model/agenticopenai@latest
go get github.com/cloudwego/eino-ext/components/retriever/milvus2@latest
go get github.com/cloudwego/eino-ext/components/tool/mcp@latestChatModel Usage (Classic Path)
Generate
resp, err := chatModel.Generate(ctx, []*schema.Message{
{Role: schema.User, Content: "Hello"},
})
fmt.Println(resp.Content)Stream
reader, err := chatModel.Stream(ctx, messages)
defer reader.Close()
for {
chunk, err := reader.Recv()
if errors.Is(err, io.EOF) { break }
if err != nil { return err }
fmt.Print(chunk.Content)
}Tool Calling
withTools, err := chatModel.WithTools([]*schema.ToolInfo{toolInfo})
resp, err := withTools.Generate(ctx, messages)
// resp.ToolCalls contains model's tool invocationsAgenticModel Usage
import (
"github.com/cloudwego/eino-ext/components/model/agenticopenai"
"github.com/cloudwego/eino/components/model"
"github.com/cloudwego/eino/schema"
)
// Create agentic model
am, _ := agenticopenai.New(ctx, &agenticopenai.Config{
Model: "gpt-4o",
APIKey: "your-key",
})
// Tools passed at call time via option for AgenticModel-interface code
resp, err := am.Generate(ctx,
[]*schema.AgenticMessage{schema.UserAgenticMessage("Search for Go tutorials")},
model.WithTools(toolInfos),
)
// Response contains typed ContentBlocks
for _, block := range resp.ContentBlocks {
switch block.Type {
case schema.ContentBlockTypeAssistantGenText:
fmt.Println(block.AssistantGenText.Text)
case schema.ContentBlockTypeFunctionToolCall:
fmt.Printf("Tool call: %s(%s)\n", block.FunctionToolCall.Name, block.FunctionToolCall.Arguments)
case schema.ContentBlockTypeReasoning:
fmt.Printf("Reasoning: %s\n", block.Reasoning.Text)
}
}RAG Components
Embedding + Indexer + Retriever form the RAG pipeline:
// 1. Embed and store documents
indexer, _ := redisIndexer.NewIndexer(ctx, &redisIndexer.IndexerConfig{
Client: redisClient, KeyPrefix: "doc:", Embedding: embedder,
})
ids, _ := indexer.Store(ctx, docs)
// 2. Retrieve relevant documents
retriever, _ := redisRetriever.NewRetriever(ctx, &redisRetriever.RetrieverConfig{
Client: redisClient, Index: "my_index", Embedding: embedder,
})
docs, _ := retriever.Retrieve(ctx, "user query", retriever.WithTopK(5))Tool Usage
MCP Tools
import mcpp "github.com/cloudwego/eino-ext/components/tool/mcp"
tools, err := mcpp.GetTools(ctx, &mcpp.Config{Cli: mcpClient})Custom InvokableTool
Implement Info() and InvokableRun() to create a custom tool.
Instructions to Agent
- Constructor signatures and Config struct names vary across implementations. Always read the provider's reference file in
reference/{type}/{impl}.mdbefore generating initialization code. - Use
BaseChatModel(classic path) orAgenticModel(agentic path) based on the user's needs. model.AgenticModeldoes not add aWithToolsmethod to the interface. Prefermodel.WithTools(...)at call time for interface-oriented code.- For ADK agents, the
ChatModelAgentConfig.Modelfield acceptsmodel.BaseModel[M]-- both paths work seamlessly. - For RAG, ensure the same Embedder model is used for both indexing and retrieval.
- See reference files for detailed per-component documentation.
Reference Files
Read files on-demand for detailed API, config, and examples. Each {type}/ directory contains an overview.md (interfaces + common patterns) and per-implementation files:
reference/model/*.md-- ChatModel and AgenticModel interfaces, tool binding, streaming, and per-provider config (openai, claude, gemini, ark, ollama, deepseek, qwen, qianfan, openrouter)reference/embedding/*.md-- Embedder interface and per-provider config (openai, ark, ollama, etc.)reference/retriever/*.md-- Retriever interface, RAG example, and per-backend config (redis, milvus2, es8)reference/indexer/*.md-- Indexer interface, indexing pipeline, and per-backend config (redis, milvus2, es8, qdrant)reference/tool/*.md-- Tool interfaces, custom tool creation, MCP integration, search tools, utility toolsreference/document/pipeline.md-- Loader, Parser, Transformer interfaces and full pipeline examplereference/prompt.md-- ChatTemplate, FString/GoTemplate/Jinja2 formats, message helpersreference/callback/*.md-- Callback handler interface, registration patterns, and per-provider config (cozeloop, apmplus, langfuse, langsmith)
APMPlus Callback
APMPlus provides tracing, metrics, and token usage tracking for Eino applications on the ByteDance APM platform.
import (
"github.com/cloudwego/eino-ext/callbacks/apmplus"
"github.com/cloudwego/eino/callbacks"
)Setup
ctx := context.Background()
cbh, shutdown, err := apmplus.NewApmplusHandler(&apmplus.Config{
Host: "apmplus-cn-beijing.volces.com:4317",
AppKey: "appkey-xxx",
ServiceName: "my-eino-app",
})
if err != nil {
log.Fatal(err)
}
defer shutdown(ctx)
callbacks.AppendGlobalHandlers(cbh)Constructor
func NewApmplusHandler(cfg *Config) (handler callbacks.Handler, shutdown func(ctx context.Context) error, err error)Returns three values:
handler-- the callback handlershutdown-- cleanup function, must be called to flush traces/metrics before exiterr-- initialization error
Config
type Config struct {
// Host is the APMPlus URL (required)
Host string
// AppKey is the authentication key (required)
AppKey string
// ServiceName identifies your service (required)
ServiceName string
// Release is the version identifier (optional)
Release string
// ResourceAttributes are custom attributes (optional)
ResourceAttributes map[string]string
}All of Host, AppKey, and ServiceName are required.
Session Support
Associate multiple requests with a session for grouped tracing:
ctx = apmplus.SetSession(ctx,
apmplus.WithSessionID("session_abc"),
apmplus.WithUserID("user_123"),
)
// Subsequent Eino calls with this ctx are grouped under the session
resp, _ := chatModel.Generate(ctx, messages)Full Example
func main() {
ctx := context.Background()
cbh, shutdown, err := apmplus.NewApmplusHandler(&apmplus.Config{
Host: "apmplus-cn-beijing.volces.com:4317",
AppKey: "appkey-xxx",
ServiceName: "eino-app",
Release: "v1.0.0",
})
if err != nil {
log.Fatal(err)
}
defer shutdown(ctx)
callbacks.AppendGlobalHandlers(cbh)
// Set session for request grouping
ctx = apmplus.SetSession(ctx,
apmplus.WithSessionID("session_001"),
apmplus.WithUserID("user_001"),
)
// All Eino component calls are now traced with APMPlus
chatModel, _ := openai.NewChatModel(ctx, &openai.ChatModelConfig{
Model: "gpt-4o",
})
resp, _ := chatModel.Generate(ctx, []*schema.Message{
{Role: schema.User, Content: "Hello"},
})
}Features tracked: traces, metrics, token usage, streaming performance, and error reporting.
CozeLoop Callback
CozeLoop provides observability and tracing for Eino applications on the Coze platform.
import (
ccb "github.com/cloudwego/eino-ext/callbacks/cozeloop"
"github.com/cloudwego/eino/callbacks"
"github.com/coze-dev/cozeloop-go"
)Setup
// Set environment variables:
// COZELOOP_WORKSPACE_ID=your-workspace-id
// COZELOOP_API_TOKEN=your-token
ctx := context.Background()
client, err := cozeloop.NewClient()
if err != nil {
panic(err)
}
defer client.Close(ctx)
handler := ccb.NewLoopHandler(client)
callbacks.AppendGlobalHandlers(handler)Constructor
func NewLoopHandler(client cozeloop.Client, opts ...Option) callbacks.HandlerThe first argument is a cozeloop.Client created via cozeloop.NewClient(). Configuration is read from environment variables (COZELOOP_WORKSPACE_ID, COZELOOP_API_TOKEN).
Options
| Option | Description |
|---|---|
WithEnableTracing(enable bool) | Enable/disable tracing (default: true) |
WithCallbackDataParser(parser) | Custom callback data parser |
WithLogger(logger) | Custom logger instance |
WithAggrMessageOutput(enable bool) | Enable aggregated message output |
WithConcatFunction[T](fn) | Register type-specific concatenation functions |
Full Example
func main() {
ctx := context.Background()
client, err := cozeloop.NewClient()
if err != nil {
log.Fatal(err)
}
defer client.Close(ctx)
handler := ccb.NewLoopHandler(client,
ccb.WithEnableTracing(true),
)
callbacks.AppendGlobalHandlers(handler)
// All Eino component calls are now traced
chatModel, _ := openai.NewChatModel(ctx, &openai.ChatModelConfig{
Model: "gpt-4o",
})
resp, _ := chatModel.Generate(ctx, []*schema.Message{
{Role: schema.User, Content: "Hello"},
})
}Langfuse Callback
Langfuse provides open-source observability and tracing for LLM applications.
import (
"github.com/cloudwego/eino-ext/callbacks/langfuse"
"github.com/cloudwego/eino/callbacks"
)Setup
cbh, flusher := langfuse.NewLangfuseHandler(&langfuse.Config{
Host: "https://cloud.langfuse.com",
PublicKey: "pk-lf-...",
SecretKey: "sk-lf-...",
})
callbacks.AppendGlobalHandlers(cbh)
defer flusher()Constructor
func NewLangfuseHandler(cfg *Config) (handler *CallbackHandler, flusher func())Returns:
handler-- the callback handlerflusher-- flush function, call before exit to send remaining events
Config
type Config struct {
Host string // Langfuse server URL (required)
PublicKey string // Public key (required)
SecretKey string // Secret key (required)
Threads int // Concurrent workers (default: 1)
Timeout time.Duration // HTTP timeout
MaxTaskQueueSize int // Event buffer size (default: 100)
FlushAt int // Batch size before sending (default: 15)
FlushInterval time.Duration // Auto-flush interval (default: 500ms)
SampleRate float64 // Event sampling rate (default: 1.0)
MaskFunc func(string) string // Mask sensitive data
MaxRetry uint64 // Max retry attempts (default: 3)
Name string // Trace name
UserID string // User identifier
SessionID string // Session identifier
Release string // Version identifier
Tags []string // Labels attached to trace
Public bool // Publicly accessible (default: false)
}Langsmith Callback
LangSmith provides tracing and evaluation for LLM applications.
import (
"github.com/cloudwego/eino-ext/callbacks/langsmith"
"github.com/cloudwego/eino/callbacks"
)Setup
cbh, err := langsmith.NewLangsmithHandler(&langsmith.Config{
APIKey: "ls-...",
APIURL: "https://api.smith.langchain.com",
})
if err != nil {
log.Fatal(err)
}
callbacks.AppendGlobalHandlers(cbh)Constructor
func NewLangsmithHandler(cfg *Config) (*CallbackHandler, error)Config
type Config struct {
APIKey string // LangSmith API key (required)
APIURL string // API URL (default: https://api.smith.langchain.com)
RunIDGen func(ctx context.Context) string // Custom run_id generator (optional)
}Callback Overview
Callback handlers observe component execution for tracing and monitoring.
Interface
// github.com/cloudwego/eino/callbacks
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
}Available Implementations
| Handler | Package | Description |
|---|---|---|
| CozeLoop | callbacks/cozeloop | Coze observability platform |
| APMPlus | callbacks/apmplus | ByteDance APM tracing and metrics |
| Langfuse | callbacks/langfuse | Langfuse observability platform |
| Langsmith | callbacks/langsmith | LangSmith tracing |
Scope
Callbacks work across all three layers of Eino:
- Components -- direct calls to ChatModel, Embedder, Retriever, etc. Compose and ADK handle callback injection automatically, but standalone component calls require explicit initialization (see below).
- Compose orchestration -- Graph, Chain, Workflow nodes are automatically traced per-node.
- ADK Agents -- ChatModelAgent, DeepAgent and their internal tool calls, multi-turn loops, and sub-agent invocations are all traced. Register once, the entire agent execution tree is observable.
A single global registration covers all layers. No extra wiring is needed for Compose graphs or ADK agents.
Registration
// Global -- applies to all components, compose graphs, and ADK agents
callbacks.AppendGlobalHandlers(handler1, handler2)
// Per-run -- pass via context in Compose graphs and Agent runners
ctx = callbacks.CtxWithHandlers(ctx, handler)Standalone Component Calls
When calling a component directly (outside a Graph or Agent), callbacks are not triggered unless you initialize them on the context with InitCallbacks. Compose graphs and ADK agents do this automatically.
import (
"github.com/cloudwego/eino/callbacks"
"github.com/cloudwego/eino/components"
)
// Initialize callbacks for a standalone ChatModel call
ctx = callbacks.InitCallbacks(ctx, &callbacks.RunInfo{
Name: "my-model",
Type: "ChatModel",
Component: components.ComponentOfChatModel,
}, handler)
resp, err := chatModel.Generate(ctx, messages)
// handler.OnStart / OnEnd / OnError are now triggeredIf a component internally calls another component and wants callbacks to propagate, use ReuseHandlers:
innerCtx := callbacks.ReuseHandlers(ctx, &callbacks.RunInfo{
Name: "inner-embedder",
Type: "Embedder",
Component: components.ComponentOfEmbedding,
})Callbacks automatically capture: component type, input/output, latency, errors, and streaming data.
Document Pipeline Reference
Loaders, parsers, and transformers form the document processing pipeline: load raw content, parse it, then split/transform for indexing.
Interfaces
// github.com/cloudwego/eino/components/document
type Loader interface {
Load(ctx context.Context, src Source, opts ...LoaderOption) ([]*schema.Document, error)
}
type Transformer interface {
Transform(ctx context.Context, src []*schema.Document, opts ...TransformerOption) ([]*schema.Document, error)
}
type Source struct {
URI string // file path or URL
}Note: Parsers are typically used internally by loaders via configuration, not called directly.
Loaders
| Loader | Import Path | Description |
|---|---|---|
| File | github.com/cloudwego/eino-ext/components/document/loader/file | Load local files |
| S3 | github.com/cloudwego/eino-ext/components/document/loader/s3 | Load from AWS S3 |
| URL | github.com/cloudwego/eino-ext/components/document/loader/url | Load from HTTP URLs |
File Loader
import "github.com/cloudwego/eino-ext/components/document/loader/file"
loader, err := file.NewFileLoader(ctx, &file.FileLoaderConfig{
UseNameAsID: true,
})
docs, err := loader.Load(ctx, document.Source{URI: "/path/to/file.txt"})URL Loader
import "github.com/cloudwego/eino-ext/components/document/loader/url"
loader, err := url.NewLoader(ctx, &url.LoaderConfig{})
docs, err := loader.Load(ctx, document.Source{URI: "https://example.com/page"})S3 Loader
import "github.com/cloudwego/eino-ext/components/document/loader/s3"
loader, err := s3.NewS3Loader(ctx, &s3.LoaderConfig{
Region: "us-east-1",
Bucket: "my-bucket",
})
docs, err := loader.Load(ctx, document.Source{URI: "s3://my-bucket/file.pdf"})Parsers
Parsers convert raw file content into structured documents. They are typically configured on loaders.
| Parser | Import Path | Formats |
|---|---|---|
| HTML | github.com/cloudwego/eino-ext/components/document/parser/html | HTML to text, extracts metadata |
github.com/cloudwego/eino-ext/components/document/parser/pdf | PDF text extraction | |
| DOCX | github.com/cloudwego/eino-ext/components/document/parser/docx | Word documents |
| XLSX | github.com/cloudwego/eino-ext/components/document/parser/xlsx | Excel spreadsheets |
HTML Parser
import "github.com/cloudwego/eino-ext/components/document/parser/html"
parser, err := html.NewParser(ctx, &html.Config{
Selector: "article", // Optional CSS selector
})PDF Parser
import "github.com/cloudwego/eino-ext/components/document/parser/pdf"
parser, err := pdf.NewPDFParser(ctx, &pdf.Config{})Transformers
Transformers operate on document slices: split, filter, merge, or re-rank.
Splitters
| Splitter | Import Path | Description |
|---|---|---|
| Recursive | github.com/cloudwego/eino-ext/components/document/transformer/splitter/recursive | Split by chunk size with overlap |
| Markdown | github.com/cloudwego/eino-ext/components/document/transformer/splitter/markdown | Split by markdown headers |
| HTML | github.com/cloudwego/eino-ext/components/document/transformer/splitter/html | Split by HTML structure |
| Semantic | github.com/cloudwego/eino-ext/components/document/transformer/splitter/semantic | Split by semantic similarity |
Recursive Splitter
import "github.com/cloudwego/eino-ext/components/document/transformer/splitter/recursive"
splitter, err := recursive.NewSplitter(ctx, &recursive.Config{
ChunkSize: 1500, // max characters per chunk
OverlapSize: 300, // overlap from previous chunk for context
})
chunks, err := splitter.Transform(ctx, docs)Markdown Splitter
import "github.com/cloudwego/eino-ext/components/document/transformer/splitter/markdown"
splitter, err := markdown.NewHeaderSplitter(ctx, &markdown.HeaderConfig{
Headers: []markdown.HeaderLevel{
{Level: 1, Name: "h1"},
{Level: 2, Name: "h2"},
},
})
chunks, err := splitter.Transform(ctx, docs)Reranker
| Reranker | Import Path | Description |
|---|---|---|
| Score | github.com/cloudwego/eino-ext/components/document/transformer/reranker/score | Rerank by score metadata |
Full Document Pipeline
Load, parse, split, and index documents end-to-end:
import (
"github.com/cloudwego/eino/components/document"
"github.com/cloudwego/eino/schema"
"github.com/cloudwego/eino-ext/components/document/loader/file"
"github.com/cloudwego/eino-ext/components/document/transformer/splitter/recursive"
embOpenai "github.com/cloudwego/eino-ext/components/embedding/openai"
redisIndexer "github.com/cloudwego/eino-ext/components/indexer/redis"
)
ctx := context.Background()
// 1. Load
loader, _ := file.NewFileLoader(ctx, &file.FileLoaderConfig{
UseNameAsID: true,
})
docs, _ := loader.Load(ctx, document.Source{URI: "/data/knowledge.txt"})
// 2. Split
splitter, _ := recursive.NewSplitter(ctx, &recursive.Config{
ChunkSize: 1500,
OverlapSize: 300,
})
chunks, _ := splitter.Transform(ctx, docs)
// 3. Create embedder
embedder, _ := embOpenai.NewEmbedder(ctx, &embOpenai.EmbeddingConfig{
APIKey: os.Getenv("OPENAI_API_KEY"),
Model: "text-embedding-3-small",
})
// 4. Index
indexer, _ := redisIndexer.NewIndexer(ctx, &redisIndexer.IndexerConfig{
Client: redisClient,
KeyPrefix: "doc:",
BatchSize: 10,
Embedding: embedder,
})
ids, _ := indexer.Store(ctx, chunks)
fmt.Printf("Indexed %d chunks\n", len(ids))For the Compose-based pipeline approach (using Graph), see the eino-compose skill.
Ark Embedder
import "github.com/cloudwego/eino-ext/components/embedding/ark"Configuration
embedder, err := ark.NewEmbedder(ctx, &ark.EmbeddingConfig{
APIKey: os.Getenv("ARK_API_KEY"),
Region: os.Getenv("ARK_REGION"),
Model: os.Getenv("ARK_MODEL"),
})Ollama Embedder
import "github.com/cloudwego/eino-ext/components/embedding/ollama"Configuration
embedder, err := ollama.NewEmbedder(ctx, &ollama.EmbeddingConfig{
BaseURL: "http://localhost:11434",
Model: "nomic-embed-text",
})OpenAI Embedder
import "github.com/cloudwego/eino-ext/components/embedding/openai"Configuration
embedder, err := openai.NewEmbedder(ctx, &openai.EmbeddingConfig{
APIKey: "your-key",
Model: "text-embedding-3-small",
// ByAzure: true, // for Azure OpenAI
// BaseURL: "https://{RESOURCE}.openai.azure.com",
})
vectors, err := embedder.EmbedStrings(ctx, []string{"hello world", "foo bar"})
// vectors[0] is the embedding for "hello world"Embedder Overview
Embedders convert text to vectors for semantic similarity search.
Interface
// github.com/cloudwego/eino/components/embedding
type Embedder interface {
EmbedStrings(ctx context.Context, texts []string, opts ...Option) ([][]float64, error)
}Returns one vector per input text. Vector dimensions are fixed by the model (e.g., 1536 for ada-002).
Implementations
| Provider | Package | Key Config |
|---|---|---|
| OpenAI | embedding/openai | APIKey, Model |
| Ark | embedding/ark | APIKey, Region, Model |
| Gemini | embedding/gemini | Client, Model |
| DashScope | embedding/dashscope | APIKey, Model |
| Ollama | embedding/ollama | BaseURL, Model |
| Qianfan | embedding/qianfan | APIKey, SecretKey |
| TencentCloud | embedding/tencentcloud | SecretID, SecretKey |
See embedding/{provider}.md for per-provider config and examples.
Elasticsearch 8 Indexer
import esIndexer "github.com/cloudwego/eino-ext/components/indexer/es8"Configuration
esClient, _ := elasticsearch.NewClient(elasticsearch.Config{
Addresses: []string{"http://localhost:9200"},
})
indexer, err := esIndexer.NewIndexer(ctx, &esIndexer.IndexerConfig{
Client: esClient,
Index: "my_index",
Embedding: embedder,
})
ids, err := indexer.Store(ctx, docs)Milvus 2.x Indexer
import milvusIndexer "github.com/cloudwego/eino-ext/components/indexer/milvus2"Configuration
milvusClient, _ := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "localhost:19530",
})
indexer, err := milvusIndexer.NewIndexer(ctx, &milvusIndexer.IndexerConfig{
Client: milvusClient,
Collection: "my_collection",
Embedding: embedder,
})
ids, err := indexer.Store(ctx, docs)Indexer Overview
Indexers store documents (with optional vector embeddings) in a backend for later retrieval.
Interface
// github.com/cloudwego/eino/components/indexer
type Indexer interface {
Store(ctx context.Context, docs []*schema.Document, opts ...Option) (ids []string, err error)
}Common options:
indexer.WithEmbedding(emb embedding.Embedder)-- embedder to generate vectors before storingindexer.WithSubIndexes(indexes ...string)-- write to logical sub-partitions
Implementations
| Backend | Package | Key Config |
|---|---|---|
| Redis | indexer/redis | Client, KeyPrefix, BatchSize, Embedding |
| Milvus 2.x | indexer/milvus2 | Client, Collection, Embedding |
| Elasticsearch 8 | indexer/es8 | Client, Index, Embedding |
| Qdrant | indexer/qdrant | Client, CollectionName, Embedding |
See indexer/{backend}.md for per-backend config and examples.
Full Indexing Pipeline
Load, parse, split, then index:
// 1. Load documents
loader, _ := file.NewFileLoader(ctx, &file.FileLoaderConfig{UseNameAsID: true})
docs, _ := loader.Load(ctx, document.Source{URI: "/path/to/file.txt"})
// 2. Split into chunks
splitter, _ := recursive.NewSplitter(ctx, &recursive.Config{
ChunkSize: 1500, OverlapSize: 300,
})
chunks, _ := splitter.Transform(ctx, docs)
// 3. Index with embeddings
ids, _ := indexer.Store(ctx, chunks)Qdrant Indexer
import qdrantIndexer "github.com/cloudwego/eino-ext/components/indexer/qdrant"Configuration
indexer, err := qdrantIndexer.NewIndexer(ctx, &qdrantIndexer.Config{
Client: qdrantClient,
CollectionName: "my_collection",
Embedding: embedder,
})
ids, err := indexer.Store(ctx, docs)Redis Indexer
import redisIndexer "github.com/cloudwego/eino-ext/components/indexer/redis"Configuration
indexer, err := redisIndexer.NewIndexer(ctx, &redisIndexer.IndexerConfig{
Client: redisClient,
KeyPrefix: "doc:",
BatchSize: 10,
Embedding: embedder,
})
ids, err := indexer.Store(ctx, docs)<!-- Copyright 2026 CloudWeGo Authors -->
Ark AgenticModel
Use agenticark when you need the model.AgenticModel path backed by Volcengine Ark Responses API and *schema.AgenticMessage.
import "github.com/cloudwego/eino-ext/components/model/agenticark"Configuration
am, err := agenticark.New(ctx, &agenticark.Config{
APIKey: "your-key", // Required unless AccessKey + SecretKey are set
Model: "endpoint-id", // Required: Ark endpoint ID
})agenticark.Config fields:
| Field | Type | Notes |
|---|---|---|
Timeout | *time.Duration | Optional; ignored when HTTPClient is set |
HTTPClient | *http.Client | Optional custom HTTP client |
RetryTimes | *int | Optional retry count |
BaseURL | string | Optional custom Ark endpoint |
Region | string | Optional region |
APIKey | string | Preferred authentication |
AccessKey | string | Alternative authentication, used with SecretKey |
SecretKey | string | Alternative authentication, used with AccessKey |
Model | string | Required model endpoint ID |
MaxTokens | *int | Optional maximum output tokens |
Temperature | *float32 | Optional, range 0.0 to 2.0 |
TopP | *float32 | Optional, range 0.0 to 1.0 |
ServiceTier | *responses.ResponsesServiceTier_Enum | Optional service tier |
Text | *responses.ResponsesText | Optional text output config |
Thinking | *responses.ResponsesThinking | Optional thinking mode config |
Reasoning | *responses.ResponsesReasoning | Optional reasoning config |
EnablePassBackReasoning | *bool | Optional; default true |
MaxToolCalls | *int64 | Optional maximum tool calls |
ParallelToolCalls | *bool | Optional parallel tool call switch |
ServerTools | []*agenticark.ServerToolConfig | Optional server-side tools |
MCPTools | []*responses.ToolMcp | Optional MCP tools |
Cache | *agenticark.CacheConfig | Optional session-cache config |
ContextManagement | *contextmanagement.ContextManagement | Optional context management |
CustomHeaders | map[string]string | Optional request headers |
ServerToolConfig supports WebSearch, ImageProcess, DoubaoApp, and KnowledgeSearch.
Call Options
Provider-specific options:
resp, err := am.Generate(ctx, messages,
agenticark.WithThinking(thinking),
agenticark.WithReasoning(reasoning),
agenticark.WithMaxToolCalls(4),
agenticark.WithParallelToolCalls(true),
agenticark.WithServerTools(serverTools),
agenticark.WithMCPTools(mcpTools),
agenticark.WithCache(cacheOpt),
agenticark.WithContextManagement(contextManagement),
agenticark.WithCustomHeaders(map[string]string{"x-trace-id": traceID}),
)Available provider options: WithReasoning, WithThinking, WithText, WithMaxToolCalls, WithParallelToolCalls, WithServerTools, WithMCPTools, WithCustomHeaders, WithCache, WithContextManagement.
Common model options also apply, including model.WithModel, model.WithMaxTokens, model.WithTemperature, model.WithTopP, model.WithTools, and model.WithAgenticToolChoice.
Cache
Session cache is configured by CacheConfig or overridden per request with WithCache:
resp, err := am.Generate(ctx, messages,
agenticark.WithCache(&agenticark.CacheOption{
HeadPreviousResponseID: previousResponseID,
SessionCache: &agenticark.SessionCacheConfig{
EnableCache: true,
ExpireAtSec: expireAt,
},
}),
)CreatePrefixCache(ctx, prefix, expireAtSec, opts...) creates server-side prefix context and returns *agenticark.CacheInfo.
Tools
For code that works against the model.AgenticModel interface, pass tools at call time:
resp, err := am.Generate(ctx,
[]*schema.AgenticMessage{schema.UserAgenticMessage("use a function tool")},
model.WithTools(toolInfos),
)Notes
model.WithStopand classicmodel.WithToolChoiceare rejected by this implementation.- Use
model.WithAgenticToolChoicefor agentic tool-choice control. - When a cached previous response is used, function/server/MCP tool population and tool choice are skipped for that request.
<!-- Copyright 2026 CloudWeGo Authors -->
DeepSeek AgenticModel
Use agenticdeepseek when you need the model.AgenticModel path backed by DeepSeek's OpenAI-compatible API and *schema.AgenticMessage.
import "github.com/cloudwego/eino-ext/components/model/agenticdeepseek"Configuration
am, err := agenticdeepseek.New(ctx, &agenticdeepseek.Config{
APIKey: "your-key", // Required
Model: "deepseek-reasoner",
})agenticdeepseek.Config fields:
| Field | Type | Notes |
|---|---|---|
APIKey | string | Required |
Timeout | time.Duration | Optional; ignored when HTTPClient is set |
HTTPClient | *http.Client | Optional custom HTTP client |
BaseURL | string | Optional; default https://api.deepseek.com |
Model | string | Required model ID |
MaxTokens | *int | Optional maximum output tokens |
Temperature | *float32 | Optional sampling temperature |
TopP | *float32 | Optional nucleus sampling |
Stop | []string | Optional stop sequences |
PresencePenalty | *float32 | Optional presence penalty |
ResponseFormatType | agenticdeepseek.ResponseFormatType | Optional response format |
FrequencyPenalty | *float32 | Optional frequency penalty |
LogProbs | *bool | Optional logprob output switch |
TopLogProbs | *int | Optional number of top logprobs |
Response format constants:
agenticdeepseek.ResponseFormatTypeText
agenticdeepseek.ResponseFormatTypeJSONObjectCall Options
This implementation is built on libs/acl/openai.AgenticClient, so it primarily uses common model options:
resp, err := am.Generate(ctx, messages,
model.WithTemperature(0.6),
model.WithMaxTokens(2048),
model.WithTopP(0.9),
model.WithTools(toolInfos),
)Common options include model.WithModel, model.WithMaxTokens, model.WithTemperature, model.WithTopP, model.WithStop, model.WithTools, and model.WithAgenticToolChoice.
Tools
For code that works against the model.AgenticModel interface, pass tools at call time:
resp, err := am.Generate(ctx,
[]*schema.AgenticMessage{schema.UserAgenticMessage("solve with tools if needed")},
model.WithTools(toolInfos),
)Notes
Newreturns an error whenconfigis nil.- Response metadata extension is extracted from the underlying OpenAI-compatible response into
AgenticResponseMeta.Extension. - Use
ResponseFormatTypeJSONObjectwhen the DeepSeek API should return JSON object output.
<!-- Copyright 2026 CloudWeGo Authors -->
Gemini AgenticModel
Use agenticgemini when you need the model.AgenticModel path backed by Google Gemini and *schema.AgenticMessage.
import "github.com/cloudwego/eino-ext/components/model/agenticgemini"Configuration
am, err := agenticgemini.NewAgenticModel(ctx, &agenticgemini.Config{
Client: genaiClient, // Required
Model: "gemini-2.0-flash",
})agenticgemini.Config fields:
| Field | Type | Notes |
|---|---|---|
Client | *genai.Client | Required Gemini client |
Model | string | Model name |
MaxTokens | *int | Optional maximum output tokens |
Temperature | *float32 | Optional, range 0.0 to 1.0 |
TopP | *float32 | Optional, range 0.0 to 1.0 |
TopK | *int32 | Optional top-k sampling |
ResponseJSONSchema | *jsonschema.Schema | Optional structured JSON schema |
EnableCodeExecution | *genai.ToolCodeExecution | Optional CodeExecution server tool |
EnableGoogleSearch | *genai.GoogleSearch | Optional GoogleSearch server tool |
EnableGoogleSearchRetrieval | *genai.GoogleSearchRetrieval | Optional GoogleSearchRetrieval server tool |
EnableComputerUse | *genai.ComputerUse | Optional ComputerUse server tool |
EnableURLContext | *genai.URLContext | Optional URLContext server tool |
EnableFileSearch | *genai.FileSearch | Optional FileSearch server tool |
EnableGoogleMaps | *genai.GoogleMaps | Optional GoogleMaps server tool |
SafetySettings | []*genai.SafetySetting | Optional safety settings |
ThinkingConfig | *genai.ThinkingConfig | Optional thinking config |
ResponseModalities | []agenticgemini.ResponseModality | Optional response modalities |
MediaResolution | genai.MediaResolution | Optional media resolution |
Cache | *agenticgemini.CacheConfig | Optional prefix-cache config |
Response modalities: ResponseModalityText, ResponseModalityImage, ResponseModalityAudio.
Call Options
Provider-specific options:
resp, err := am.Generate(ctx, messages,
agenticgemini.WithTopK(40),
agenticgemini.WithThinkingConfig(thinkingConfig),
agenticgemini.WithResponseJSONSchema(jsonSchema),
agenticgemini.WithResponseModalities([]agenticgemini.ResponseModality{
agenticgemini.ResponseModalityText,
}),
agenticgemini.WithCachedContentName("cachedContents/abc"),
)Available provider options: WithTopK, WithResponseJSONSchema, WithThinkingConfig, WithResponseModalities, WithCachedContentName.
Common model options also apply, including model.WithModel, model.WithMaxTokens, model.WithTemperature, model.WithTopP, model.WithTools, and model.WithAgenticToolChoice.
Cache
Prefix cache is created with CreatePrefixCache:
cached, err := am.CreatePrefixCache(ctx, prefixMessages, model.WithTools(toolInfos))
if err != nil {
return err
}
resp, err := am.Generate(ctx, messages,
agenticgemini.WithCachedContentName(cached.Name),
)CacheConfig supports TTL and ExpireTime when creating cached content.
Tools
For code that works against the model.AgenticModel interface, pass tools at call time:
resp, err := am.Generate(ctx,
[]*schema.AgenticMessage{schema.UserAgenticMessage("call a function if needed")},
model.WithTools(toolInfos),
)Notes
GenerateandStreamreject empty input withgemini input is empty.- Gemini server tools are configured through the
Enable*fields onConfig. - Tool choice should use
model.WithAgenticToolChoice; avoid classicmodel.WithToolChoicefor agentic messages.
<!-- Copyright 2026 CloudWeGo Authors -->
OpenAI AgenticModel
Use agenticopenai when you need the model.AgenticModel path backed by OpenAI Responses API and *schema.AgenticMessage.
import "github.com/cloudwego/eino-ext/components/model/agenticopenai"Configuration
am, err := agenticopenai.New(ctx, &agenticopenai.Config{
APIKey: "your-key", // Required
Model: "gpt-4o", // Required
})agenticopenai.Config fields:
| Field | Type | Notes |
|---|---|---|
ByAzure | bool | Use Azure OpenAI authentication when true |
BaseURL | string | Optional custom endpoint |
APIKey | string | Required |
Timeout | *time.Duration | Optional request timeout |
HTTPClient | *http.Client | Optional custom HTTP client |
MaxRetries | *int | Optional SDK retry count |
Model | string | Required model ID |
MaxTokens | *int | Optional maximum output tokens |
Temperature | *float32 | Optional, range 0.0 to 2.0 |
TopP | *float32 | Optional, range 0.0 to 1.0 |
ServiceTier | *responses.ResponseNewParamsServiceTier | Optional service tier |
Text | *responses.ResponseTextConfigParam | Optional text output config |
Reasoning | *responses.ReasoningParam | Optional reasoning config |
Store | *bool | Optional server-side response storage |
MaxToolCalls | *int | Optional maximum tool calls |
ParallelToolCalls | *bool | Optional parallel tool call switch |
Include | []responses.ResponseIncludable | Optional additional response fields |
ServerTools | []*agenticopenai.ServerToolConfig | Optional hosted tools |
MCPTools | []*responses.ToolMcpParam | Optional MCP tools |
Truncation | *responses.ResponseNewParamsTruncation | Optional truncation behavior |
CustomHeaders | map[string]string | Optional request headers |
ExtraFields | map[string]any | Optional raw JSON fields added to the request |
ServerToolConfig supports WebSearch, FileSearch, CodeInterpreter, and Shell.
Call Options
Provider-specific options:
resp, err := am.Generate(ctx, messages,
agenticopenai.WithReasoning(reasoning),
agenticopenai.WithMaxToolCalls(4),
agenticopenai.WithParallelToolCalls(true),
agenticopenai.WithServerTools(serverTools),
agenticopenai.WithMCPTools(mcpTools),
agenticopenai.WithPromptCacheKey("stable-prefix-key"),
agenticopenai.WithCustomHeaders(map[string]string{"x-trace-id": traceID}),
agenticopenai.WithExtraFields(map[string]any{"metadata": map[string]string{"env": "prod"}}),
)Available provider options: WithStore, WithPromptCacheKey, WithReasoning, WithText, WithMaxToolCalls, WithParallelToolCalls, WithServerTools, WithMCPTools, WithCustomHeaders, WithExtraFields, WithTruncation.
Common model options also apply, including model.WithModel, model.WithMaxTokens, model.WithTemperature, model.WithTopP, model.WithTools, model.WithDeferredTools, model.WithToolSearchTool, and model.WithAgenticToolChoice.
Tools
For code that works against the model.AgenticModel interface, pass tools at call time:
resp, err := am.Generate(ctx,
[]*schema.AgenticMessage{schema.UserAgenticMessage("search the web")},
model.WithTools(toolInfos),
)Do not rely on concrete-only methods when documenting general AgenticModel usage.
Notes
model.WithStopand classicmodel.WithToolChoiceare rejected by this implementation.- Use
model.WithAgenticToolChoicefor agentic tool-choice control. model.WithDeferredToolsautomatically adds hosted tool search when no explicit tool-search tool is provided.
<!-- Copyright 2026 CloudWeGo Authors -->
Qwen AgenticModel
Use agenticqwen when you need the model.AgenticModel path backed by Qwen/DashScope's OpenAI-compatible API and *schema.AgenticMessage.
import "github.com/cloudwego/eino-ext/components/model/agenticqwen"Configuration
am, err := agenticqwen.New(ctx, &agenticqwen.Config{
APIKey: "your-key", // Required
Model: "qwen-plus",
})agenticqwen.Config fields:
| Field | Type | Notes |
|---|---|---|
APIKey | string | Required |
Timeout | time.Duration | Optional; ignored when HTTPClient is set |
HTTPClient | *http.Client | Optional custom HTTP client |
BaseURL | string | Optional; default https://dashscope-intl.aliyuncs.com/compatible-mode/v1 |
Model | string | Required model ID |
MaxTokens | *int | Optional maximum output tokens |
Temperature | *float32 | Optional, range 0.0 to 2.0 |
TopP | *float32 | Optional, range 0.0 to 1.0 |
Stop | []string | Optional stop sequences |
PresencePenalty | *float32 | Optional presence penalty |
Seed | *int | Optional deterministic sampling seed |
FrequencyPenalty | *float32 | Optional frequency penalty |
LogitBias | map[string]int | Optional token bias map |
User | *string | Optional end-user identifier |
EnableThinking | *bool | Optional thinking mode switch |
PreserveThinking | *bool | Optional multi-turn thinking preservation |
Modalities | []agenticqwen.Modality | Optional output modalities |
Audio | *agenticqwen.AudioConfig | Required when Modalities includes audio |
Modality and audio constants:
agenticqwen.ModalityText
agenticqwen.ModalityAudio
agenticqwen.AudioFormatWav
agenticqwen.AudioVoiceCherry
agenticqwen.AudioVoiceSerena
agenticqwen.AudioVoiceEthan
agenticqwen.AudioVoiceChelsieCall Options
Provider-specific options:
resp, err := am.Generate(ctx, messages,
agenticqwen.WithEnableThinking(true),
agenticqwen.WithPreserveThinking(true),
model.WithTools(toolInfos),
)Available provider options: WithEnableThinking, WithPreserveThinking.
Common model options also apply, including model.WithModel, model.WithMaxTokens, model.WithTemperature, model.WithTopP, model.WithStop, model.WithTools, and model.WithAgenticToolChoice.
Audio Output
For Qwen-Omni models that return audio, set both Modalities and Audio:
am, err := agenticqwen.New(ctx, &agenticqwen.Config{
APIKey: "your-key",
Model: "qwen-omni-turbo",
Modalities: []agenticqwen.Modality{
agenticqwen.ModalityText,
agenticqwen.ModalityAudio,
},
Audio: &agenticqwen.AudioConfig{
Format: agenticqwen.AudioFormatWav,
Voice: agenticqwen.AudioVoiceCherry,
},
})Tools
For code that works against the model.AgenticModel interface, pass tools at call time:
resp, err := am.Generate(ctx,
[]*schema.AgenticMessage{schema.UserAgenticMessage("use tools if needed")},
model.WithTools(toolInfos),
)Notes
Newreturns an error whenconfigis nil.EnableThinkingandPreserveThinkingare encoded into provider-specific extra fields before calling the underlying OpenAI-compatible client.- Response metadata extension is extracted from the underlying OpenAI-compatible response into
AgenticResponseMeta.Extension.
Ark (Volcengine) ChatModel
import "github.com/cloudwego/eino-ext/components/model/ark"Configuration
chatModel, err := ark.NewChatModel(ctx, &ark.ChatModelConfig{
APIKey: "your-key", // Required (or AccessKey+SecretKey)
Model: "endpoint-id", // Required: Ark endpoint ID
// BaseURL: "https://ark.cn-beijing.volces.com/api/v3", // Default
})Claude ChatModel
import "github.com/cloudwego/eino-ext/components/model/claude"Configuration
chatModel, err := claude.NewChatModel(ctx, &claude.Config{
APIKey: "your-key", // Required
Model: "claude-sonnet-4-20250514", // Required
MaxTokens: 3000, // Required
// AWS Bedrock:
// ByBedrock: true,
// AccessKey: "...",
// SecretAccessKey: "...",
// Region: "us-west-2",
// Google Vertex AI:
// ByVertex: true,
// VertexProjectID: "your-project-id",
// VertexRegion: "us-east5",
})Prompt Caching
Claude automatically caches repeated prefixes, but with auto-cache explicitly enabled, cache hits are billed at a significantly lower rate. Always enable it for multi-turn conversations or when using tools/system prompts.
Auto Cache (Recommended)
Enable via per-request option. The caching strategy automatically sets cache breakpoints on system messages, tool definitions, and the last message of each turn.
resp, err := chatModel.Generate(ctx, messages,
claude.WithEnableAutoCache(true),
)Manual Breakpoints
For fine-grained control, set cache breakpoints on specific messages or tool definitions:
// Cache a specific message (e.g., a long system prompt)
messages[0] = claude.SetMessageBreakpoint(messages[0])
// Cache a tool definition
toolInfo = claude.SetToolInfoBreakpoint(toolInfo)Content before a breakpoint is cached. Subsequent requests reuse the cached prefix, reducing both latency and cost.
Extended Thinking
resp, err := chatModel.Generate(ctx, messages, claude.WithThinking(&claude.Thinking{
Enable: true,
BudgetTokens: 1024,
}))
thinking, ok := claude.GetThinking(resp)DeepSeek ChatModel
import "github.com/cloudwego/eino-ext/components/model/deepseek"Configuration
chatModel, err := deepseek.NewChatModel(ctx, &deepseek.ChatModelConfig{
APIKey: "your-key", // Required
Model: "deepseek-reasoner", // Required
// BaseURL: "https://api.deepseek.com/", // Default
})Reasoning Content
reasoning, ok := deepseek.GetReasoningContent(resp)Gemini ChatModel
import "github.com/cloudwego/eino-ext/components/model/gemini"Configuration
client, _ := genai.NewClient(ctx, &genai.ClientConfig{APIKey: "your-key"})
chatModel, err := gemini.NewChatModel(ctx, &gemini.Config{
Client: client, // Required: *genai.Client
Model: "gemini-2.5-flash", // Required
ThinkingConfig: &genai.ThinkingConfig{
IncludeThoughts: true,
},
})Ollama ChatModel
import "github.com/cloudwego/eino-ext/components/model/ollama"Configuration
chatModel, err := ollama.NewChatModel(ctx, &ollama.ChatModelConfig{
BaseURL: "http://localhost:11434", // Required
Model: "llama3", // Required
})OpenAI ChatModel
import "github.com/cloudwego/eino-ext/components/model/openai"Configuration
chatModel, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
APIKey: "your-key", // Required
Model: "gpt-4o", // Required
BaseURL: "", // Optional, custom endpoint
Temperature: func() *float32 { t := float32(0.7); return &t }(), // Optional, 0.0-2.0
MaxCompletionTokens: func() *int { t := 4096; return &t }(), // Optional
ReasoningEffort: openai.ReasoningEffortLevelHigh, // Optional
})Azure OpenAI
Use the OpenAI model with Azure-specific config:
chatModel, err := openai.NewChatModel(ctx, &openai.ChatModelConfig{
ByAzure: true,
BaseURL: "https://{RESOURCE_NAME}.openai.azure.com",
APIKey: os.Getenv("AZURE_OPENAI_API_KEY"),
APIVersion: "2024-06-01",
Model: "gpt-4o",
})Request/Response Modifiers
Many providers offer OpenAI-compatible APIs with extra fields. Use these options to customize the raw request/response without forking the model implementation.
WithRequestPayloadModifier
Modify the serialized JSON request body before it is sent. Use this to inject provider-specific fields.
resp, err := chatModel.Generate(ctx, messages,
openai.WithRequestPayloadModifier(
func(ctx context.Context, msgs []*schema.Message, rawBody []byte) ([]byte, error) {
// Parse rawBody, add extra fields, return modified JSON
var body map[string]any
json.Unmarshal(rawBody, &body)
body["custom_field"] = "value"
return json.Marshal(body)
},
),
)WithResponseMessageModifier
Transform the output message using the raw response body. Use this to extract provider-specific fields from non-streaming responses.
resp, err := chatModel.Generate(ctx, messages,
openai.WithResponseMessageModifier(
func(ctx context.Context, msg *schema.Message, rawBody []byte) (*schema.Message, error) {
// Extract custom data from rawBody into msg.Extra or msg.Content
return msg, nil
},
),
)WithResponseChunkMessageModifier
Transform each streaming chunk using the raw chunk body. When end is true (stream finished), msg and rawBody may be nil.
stream, err := chatModel.Stream(ctx, messages,
openai.WithResponseChunkMessageModifier(
func(ctx context.Context, msg *schema.Message, rawBody []byte, end bool) (*schema.Message, error) {
if end {
return msg, nil
}
// Process each chunk
return msg, nil
},
),
)WithExtraFields
A simpler alternative when you only need to add top-level fields to the request body:
resp, err := chatModel.Generate(ctx, messages,
openai.WithExtraFields(map[string]any{
"custom_param": "value",
}),
)OpenRouter ChatModel
import "github.com/cloudwego/eino-ext/components/model/openrouter"Configuration
chatModel, err := openrouter.NewChatModel(ctx, &openrouter.Config{
APIKey: "your-key", // Required
Model: "anthropic/claude-sonnet-4-20250514", // Required
// BaseURL: "https://openrouter.ai/api/v1", // Default
Reasoning: &openrouter.Reasoning{
Effort: openrouter.EffortOfMedium,
},
})Model Overview
Eino has two model paths:
- Classic ChatModel uses
*schema.Message. - AgenticModel uses
*schema.AgenticMessageand preserves native block-based content.
Interfaces
type BaseModel[M any] interface {
Generate(ctx context.Context, input []M, opts ...Option) (M, error)
Stream(ctx context.Context, input []M, opts ...Option) (*schema.StreamReader[M], error)
}
type BaseChatModel = BaseModel[*schema.Message]
type AgenticModel = BaseModel[*schema.AgenticMessage]
type ToolCallingChatModel interface {
BaseChatModel
WithTools(tools []*schema.ToolInfo) (ToolCallingChatModel, error)
}Tool Binding
Use WithTools to bind tools (returns a new instance, safe for concurrent use):
tools := []*schema.ToolInfo{
{
Name: "get_weather",
Desc: "Get current weather for a city",
ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
"city": {Type: "string", Desc: "City name", Required: true},
}),
},
}
withTools, err := chatModel.WithTools(tools)
resp, err := withTools.Generate(ctx, messages)
for _, tc := range resp.ToolCalls {
fmt.Printf("Tool: %s, Args: %s\n", tc.Function.Name, tc.Function.Arguments)
}Streaming
reader, err := chatModel.Stream(ctx, messages)
if err != nil {
return err
}
defer reader.Close()
for {
chunk, err := reader.Recv()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
return err
}
fmt.Print(chunk.Content)
}To concatenate stream chunks into a single message:
chunks := make([]*schema.Message, 0)
for { /* collect chunks */ }
msg, err := schema.ConcatMessages(chunks)AgenticModel
AgenticModel does not add a tool-binding method to the interface. Pass tools at request time:
resp, err := agenticModel.Generate(ctx,
[]*schema.AgenticMessage{schema.UserAgenticMessage("use tools if needed")},
model.WithTools(toolInfos),
)Use provider-specific references for constructor and config details:
| Provider | Reference |
|---|---|
| OpenAI | reference/model/agenticopenai.md |
| Gemini | reference/model/agenticgemini.md |
| DeepSeek | reference/model/agenticdeepseek.md |
| Ark | reference/model/agenticark.md |
| Qwen | reference/model/agenticqwen.md |
Qianfan (Baidu) ChatModel
import "github.com/cloudwego/eino-ext/components/model/qianfan"Configuration
chatModel, err := qianfan.NewChatModel(ctx, &qianfan.ChatModelConfig{
APIKey: "your-key",
SecretKey: "your-secret",
Model: "ernie-4.0",
})Qwen ChatModel
import "github.com/cloudwego/eino-ext/components/model/qwen"Configuration
chatModel, err := qwen.NewChatModel(ctx, &qwen.ChatModelConfig{
BaseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1", // Required
APIKey: "your-key", // Required
Model: "qwen-plus", // Required
})Prompt Reference
ChatTemplate formats prompt messages with variable substitution.
ChatTemplate Interface
// github.com/cloudwego/eino/components/prompt
type ChatTemplate interface {
Format(ctx context.Context, vs map[string]any, opts ...Option) ([]*schema.Message, error)
}Creating Templates
FromMessages
Build a template from multiple message templates:
import "github.com/cloudwego/eino/components/prompt"
template := prompt.FromMessages(ctx,
schema.SystemMessage("You are a {role}. {instructions}"),
schema.UserMessage("{user_input}"),
)
messages, err := template.Format(ctx, map[string]any{
"role": "helpful assistant",
"instructions": "Be concise.",
"user_input": "What is Eino?",
})
// Returns []*schema.Message with variables substitutedFString Format
Uses {variable} syntax -- simple and direct:
msg := &schema.Message{
Role: schema.System,
Content: "You are a {role}. Help the user with {task}.",
}
// schema.Message implements ChatTemplate
messages, err := msg.Format(ctx, map[string]any{
"role": "code reviewer",
"task": "reviewing Go code",
})GoTemplate Format
Uses Go text/template syntax for complex logic:
template := prompt.FromMessages(ctx,
&schema.Message{
Role: schema.System,
Content: "{{if .expert}}As an expert{{end}} help with {{.topic}}",
// Template type is inferred from syntax
},
)Jinja2 Format
// Uses Jinja2 syntax
msg := &schema.Message{
Role: schema.System,
Content: "{% if level == 'expert' %}Expert mode{% endif %} Topic: {{topic}}",
}Message Helpers
schema.SystemMessage("system prompt")
schema.UserMessage("user question")
schema.AssistantMessage("assistant response")
schema.ToolMessage("tool result", "tool-call-id")Elasticsearch 8 Retriever
import "github.com/cloudwego/eino-ext/components/retriever/es8"Configuration
esClient, _ := elasticsearch.NewClient(elasticsearch.Config{
Addresses: []string{"http://localhost:9200"},
})
retriever, err := es8.NewRetriever(ctx, &es8.RetrieverConfig{
Client: esClient,
Index: "my_index",
TopK: 5,
Embedding: embedder,
SearchMode: search_mode.NewApproximateMode("content_vector"),
})Milvus 2.x Retriever
import milvus2 "github.com/cloudwego/eino-ext/components/retriever/milvus2"Configuration
milvusClient, _ := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "localhost:19530",
Username: "user",
Password: "pass",
})
retriever, err := milvus2.NewRetriever(ctx, &milvus2.RetrieverConfig{
Client: milvusClient,
Collection: "my_collection",
Embedding: embedder,
SearchMode: search_mode.NewApproximateSearchMode(10),
DocumentParser: nil, // custom result-to-document parser
})Retriever Overview
Retrievers find the most relevant documents by vector similarity.
Interface
// github.com/cloudwego/eino/components/retriever
type Retriever interface {
Retrieve(ctx context.Context, query string, opts ...Option) ([]*schema.Document, error)
}Common options:
retriever.WithTopK(k int)-- max number of resultsretriever.WithScoreThreshold(t float64)-- min relevance score filterretriever.WithEmbedding(emb embedding.Embedder)-- embedder for query vectorization
Implementations
| Backend | Package | Key Config |
|---|---|---|
| Redis | retriever/redis | Client, Index, VectorField, TopK |
| Milvus 2.x | retriever/milvus2 | Client, Collection, SearchMode |
| Elasticsearch 8 | retriever/es8 | Client, Index, SearchMode |
| Qdrant | retriever/qdrant | Client, CollectionName |
See retriever/{backend}.md for per-backend config and examples.
RAG Retrieval Example
// The retriever handles embedding internally when Embedding is configured
docs, err := retriever.Retrieve(ctx, "How does Eino handle streaming?",
retriever.WithTopK(5),
)
for _, doc := range docs {
fmt.Printf("ID: %s\nContent: %s\nScore: %v\n\n",
doc.ID, doc.Content, doc.MetaData["score"])
}The same Embedder model must be used for indexing and retrieval. Mismatched models will produce incorrect similarity scores.
Qdrant Retriever
import qdrantRetriever "github.com/cloudwego/eino-ext/components/retriever/qdrant"Configuration
retriever, err := qdrantRetriever.NewRetriever(ctx, &qdrantRetriever.Config{
Client: qdrantClient,
CollectionName: "my_collection",
Embedding: embedder,
})
docs, err := retriever.Retrieve(ctx, "what is eino?")Redis Retriever
import redisRetriever "github.com/cloudwego/eino-ext/components/retriever/redis"Configuration
// Redis client MUST use Protocol 2 for FT.SEARCH
client := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Protocol: 2,
})
client.Options().UnstableResp3 = true
retriever, err := redisRetriever.NewRetriever(ctx, &redisRetriever.RetrieverConfig{
Client: client,
Index: "my_index",
VectorField: "content_vector",
TopK: 5,
Embedding: embedder,
})
docs, err := retriever.Retrieve(ctx, "what is eino?")MCP Tool Integration
The MCP (Model Context Protocol) component converts MCP server tools into Eino tools.
import mcpp "github.com/cloudwego/eino-ext/components/tool/mcp"SSE-based MCP Server
import (
"github.com/mark3labs/mcp-go/client"
"github.com/mark3labs/mcp-go/mcp"
mcpp "github.com/cloudwego/eino-ext/components/tool/mcp"
)
cli, _ := client.NewSSEMCPClient("http://localhost:12345/sse")
cli.Start(ctx)
initReq := mcp.InitializeRequest{}
initReq.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
initReq.Params.ClientInfo = mcp.Implementation{Name: "my-app", Version: "1.0.0"}
cli.Initialize(ctx, initReq)
tools, err := mcpp.GetTools(ctx, &mcpp.Config{
Cli: cli,
// ToolNameList: []string{"calculate"}, // Optional: filter specific tools
})
// Each tool implements InvokableTool
for _, t := range tools {
info, _ := t.Info(ctx)
fmt.Println(info.Name, info.Desc)
}Stdio-based MCP Server
cli, _ := client.NewStdioMCPClient("npx", nil, "-y", "@modelcontextprotocol/server-xxx")Tool Overview
Tools are functions that a ChatModel can invoke.
Interfaces
// github.com/cloudwego/eino/components/tool
type BaseTool interface {
Info(ctx context.Context) (*schema.ToolInfo, error)
}
type InvokableTool interface {
BaseTool
InvokableRun(ctx context.Context, argumentsInJSON string, opts ...Option) (string, error)
}
type StreamableTool interface {
BaseTool
StreamableRun(ctx context.Context, argumentsInJSON string, opts ...Option) (*schema.StreamReader[string], error)
}
// Enhanced variants accept/return structured multimodal data
type EnhancedInvokableTool interface {
BaseTool
InvokableRun(ctx context.Context, toolArgument *schema.ToolArgument, opts ...Option) (*schema.ToolResult, error)
}
type EnhancedStreamableTool interface {
BaseTool
StreamableRun(ctx context.Context, toolArgument *schema.ToolArgument, opts ...Option) (*schema.StreamReader[*schema.ToolResult], error)
}ToolInfo Schema
toolInfo := &schema.ToolInfo{
Name: "get_weather",
Desc: "Get current weather for a city",
ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
"city": {Type: "string", Desc: "City name", Required: true},
"unit": {Type: "string", Desc: "Temperature unit", Enum: []string{"celsius", "fahrenheit"}},
}),
}Custom Tool Creation
Using utils.InferTool (recommended)
import "github.com/cloudwego/eino/components/tool/utils"
type WeatherInput struct {
City string `json:"city" jsonschema:"required" jsonschema_description:"City name"`
Unit string `json:"unit" jsonschema:"enum=celsius|fahrenheit" jsonschema_description:"Temperature unit"`
}
weatherTool, _ := utils.InferTool(
"get_weather",
"Get current weather for a city",
func(ctx context.Context, input *WeatherInput) (string, error) {
return fmt.Sprintf("Weather in %s: 22 %s", input.City, input.Unit), nil
},
)Manual implementation
type MyTool struct{}
func (t *MyTool) Info(ctx context.Context) (*schema.ToolInfo, error) {
return &schema.ToolInfo{
Name: "my_tool",
Desc: "Does something useful",
ParamsOneOf: schema.NewParamsOneOfByParams(map[string]*schema.ParameterInfo{
"input": {Type: "string", Desc: "The input", Required: true},
}),
}, nil
}
func (t *MyTool) InvokableRun(ctx context.Context, argumentsInJSON string, opts ...tool.Option) (string, error) {
var args struct{ Input string `json:"input"` }
json.Unmarshal([]byte(argumentsInJSON), &args)
return "result for: " + args.Input, nil
}Using Tools with ChatModel
// 1. Collect tool infos
var toolInfos []*schema.ToolInfo
for _, t := range tools {
info, _ := t.Info(ctx)
toolInfos = append(toolInfos, info)
}
// 2. Bind to model
modelWithTools, _ := chatModel.WithTools(toolInfos)
// 3. Generate -- model may produce tool calls
resp, _ := modelWithTools.Generate(ctx, messages)
// 4. Handle tool calls
for _, tc := range resp.ToolCalls {
result, _ := matchingTool.InvokableRun(ctx, tc.Function.Arguments)
messages = append(messages, resp)
messages = append(messages, &schema.Message{
Role: schema.Tool,
Content: result,
ToolCallID: tc.ID,
})
}
resp, _ = modelWithTools.Generate(ctx, messages) // final answerFor automated tool execution loops, use ToolsNode in eino or the ReAct agent pattern.
Search Tools
Google Search
import "github.com/cloudwego/eino-ext/components/tool/googlesearch"
tool, err := googlesearch.NewTool(ctx, &googlesearch.Config{
APIKey: "your-google-api-key",
SearchEngineID: "your-cse-id",
NumResults: 5,
})DuckDuckGo Search (v2)
import "github.com/cloudwego/eino-ext/components/tool/duckduckgo/v2"
tool, err := duckduckgo.NewTool(ctx, &duckduckgo.Config{
MaxResults: 5,
})Bing Search
import "github.com/cloudwego/eino-ext/components/tool/bingsearch"
tool, err := bingsearch.NewTool(ctx, &bingsearch.Config{
APIKey: "your-bing-api-key",
MaxResults: 5,
})Utility Tools
HTTP Request
import "github.com/cloudwego/eino-ext/components/tool/httprequest"
tool, err := httprequest.NewTool(ctx, &httprequest.Config{})
// Makes HTTP requests based on model-generated parametersCommand Line
import "github.com/cloudwego/eino-ext/components/tool/commandline"
tool, err := commandline.NewTool(ctx, &commandline.Config{})
// Executes shell commandsBrowser Use
import "github.com/cloudwego/eino-ext/components/tool/browseruse"
tool, err := browseruse.NewTool(ctx, &browseruse.Config{})
// Browser automation tool