Eino Study Notes — Appendix 3
Eino Study Notes — Appendix 3: Lambda Writing, Debugging Tools, and Visualization
This note was generated with AI assistance, but the code-reading order should be fine (all examples use the official Eino examples; personally, I find the official tutorials a bit hard to follow).
In principle, I think the appendices are just for reference — you can skim them and look things up when needed.
Appendix 3: Lambda Writing, Debugging Tools, and Visualization
📂 Source repo: github.com/cloudwego/eino-examples↗
📖 Series docs: Intro Notes | Agentic Advanced | Appendix 1 Flow | Appendix 2 Components | Appendix 3 Tools
📁 Code root:
components/lambda/,devops/📖 Prerequisites: Lambda is the most flexible node type in Compose orchestration; debugging and visualization are essential tools for development and troubleshooting.
At a Glance: The Relationship Between the Three Tools
Development stage Production stage──────── ────────Write business logic with Lambda ↓Orchestrate nodes with Graph/Chain ↓Visualize (Mermaid) Debug (Devops)View topology structure Test via graphical UI ↓Confirm structure is correct Confirm logic is correct ↓ Commit code → run in production📇 Quick-Reference Card for This Appendix
Four ways to create a Lambda: InvokableLambda(fn) ← Simplest InvokableLambdaWithOption(fn) ← Needs custom params AnyLambda(invoke, stream, collect, transform) ← All modes ToList[T]() ← Type conversion T→[]T
Debugging: devops.Init(ctx) → Chain/Graph.Compile → test via graphical UIVisualization: NewMermaidGenerator(dir) → Compile(WithGraphCompileCallbacks(gen))1. The Complete Guide to Writing Lambda Nodes
📁
components/lambda/lambda.go📖 Official docs: https://www.cloudwego.io/zh/docs/eino/core_modules/components/lambda_guide/↗
1.1 What is a Lambda
A Lambda is the “all-purpose node” in Compose orchestration — you can wrap any Go function as a node in a Graph/Chain:
Built-in Graph nodes: ChatModel, ToolsNode, ChatTemplate ← provided by the frameworkLambda node: any function you write ← provided by yourself1.2 Lambda Decision Tree
What do you need?│├─ Simplest: ctx+input → output│ └─→ compose.InvokableLambda(fn)│├─ Need custom params│ └─→ compose.InvokableLambdaWithOption(fn)│├─ Need streaming (Stream/Transform)│ └─→ compose.AnyLambda(invoke, stream, collect, transform)│├─ Only type conversion T → []T│ └─→ compose.ToList[T]()│└─ Parse JSON returned by ChatModel └─→ compose.MessageParser(parser)1.3 Four Creation Methods
Method 1: InvokableLambda (Simplest)
lambda := compose.InvokableLambda( func(ctx context.Context, input string) (output string, err error) { return strings.ToUpper(input), nil },)Method 2: InvokableLambdaWithOption (with custom params)
type Options struct { Field1 string }type MyOption func(*Options)
lambda := compose.InvokableLambdaWithOption( func(ctx context.Context, input string, opts ...MyOption) (output string, err error) { o := &Options{} for _, opt := range opts { opt(o) } return "", nil },)Method 3: AnyLambda (Full-featured: Invoke/Stream/Collect/Transform)
lambda, _ := compose.AnyLambda( func(ctx context.Context, input string, opts ...MyOption) (output string, err error) { return "", nil }, func(ctx context.Context, input string, opts ...MyOption) (output *schema.StreamReader[string], err error) { return nil, nil }, func(ctx context.Context, input *schema.StreamReader[string], opts ...MyOption) (output string, err error) { return "", nil }, func(ctx context.Context, input *schema.StreamReader[string], opts ...MyOption) (output *schema.StreamReader[string], err error) { return nil, nil },)Method 4: ToList (Type-Conversion Lambda)
// ChatModel returns *schema.Message; bridge when downstream needs []*schema.Messagechain.AppendLambda(compose.ToList[*schema.Message]())1.4 Using Lambda in Chain and Graph
// Chainchain := compose.NewChain[string, string]()chain.AppendLambda( compose.InvokableLambda(func(ctx context.Context, input string) (string, error) { return input + " processed", nil }), compose.WithNodeName("step1"),)
// Graphgraph := compose.NewGraph[string, *MyStruct]()graph.AddLambdaNode("node1", compose.InvokableLambda(func(ctx context.Context, input string) (*MyStruct, error) { return &MyStruct{ID: 1}, nil }), compose.WithStatePreHandler(func(ctx context.Context, input string, state *myState) (string, error) { return input, nil // Read/write State before node execution }),)1.5 Special-Type Lambda: MessageParser
Parse the Content (JSON string) of a *schema.Message into a Go struct:
parser := schema.NewMessageJSONParser[*MyStruct](&schema.MessageJSONParseConfig{ ParseFrom: schema.MessageParseFromContent,})parserLambda := compose.MessageParser(parser)
chain := compose.NewChain[*schema.Message, *MyStruct]()chain.AppendLambda(parserLambda)2. Eino Devops Debugging Tool
📁
devops/debug/
2.1 Start the Debugging Service
import ( "github.com/cloudwego/eino-ext/devops" "os/signal" "syscall")
func main() { err := devops.Init(ctx) // 1. Start the HTTP debug UI
chain.RegisterSimpleChain(ctx) // 2. Register your Chain/Graph graph.RegisterSimpleGraph(ctx)
sigs := make(chan os.Signal, 1) // 3. Block and wait signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) <-sigs}💡
devops.Init(ctx)only needs to be called once. The registered Chain/Graph will appear in the dropdown menu of the debug UI.
2.2 Debugging Tip for Any-Type Input
When the Graph’s input type is map[string]any, type annotations are needed:
{ "name": { "_value": "alice", "_eino_go_type": "string" }, "score": { "_value": "99", "_eino_go_type": "int" }}3. Visualization Tool: Mermaid Diagram Generation
📁
devops/visualize/mermaid.go
3.1 Basic Usage
import "github.com/cloudwego/eino-examples/devops/visualize"
gen := visualize.NewMermaidGenerator("output/dir") // Specify the output directory
runner, _ := g.Compile(context.Background(), compose.WithGraphCompileCallbacks(gen), compose.WithGraphName("MyGraph"),)Output files: output/dir/MyGraph (Markdown) + MyGraph.png (automatically rendered topology diagram).
3.2 Visualization Rules
| Node type | Mermaid shape |
|---|---|
| START / END | ([START]) ([END]) stadium/rounded rectangle |
| Normal node | [node name<br/>(component type)] box |
| Lambda node | (node name<br/>(Lambda)) rounded box |
| Nested subgraph | subgraph ... end subgraph box |
| Branch | {"branch"} diamond |
3.3 Image Generation Strategy
- Prefer mmdc (Mermaid CLI):
mmdc -i input.mmd -o output.png - Fallback to chromedp: headless browser renders SVG → screenshot saved as PNG
4. Lambda Quick Reference Table
| Type | Creation function | Required params | Common options |
|---|---|---|---|
| Pure-function Lambda | compose.InvokableLambda(fn) | fn | — |
| Option-bearing Lambda | compose.InvokableLambdaWithOption(fn) | fn | Custom Option |
| Full-mode Lambda | compose.AnyLambda(invoke, stream, collect, transform) | 4 functions | Custom Option |
| List wrapper | compose.ToList[T]() | — (generic) | — |
| Message parser | compose.MessageParser(parser) | schema.MessageJSONParser | — |
Common import paths
// Lambda"github.com/cloudwego/eino/compose" // InvokableLambda, AnyLambda, ToList, MessageParser"github.com/cloudwego/eino/schema" // NewMessageJSONParser, MessageParseFromContent
// Debugging"github.com/cloudwego/eino-ext/devops" // Init
// Visualization"github.com/cloudwego/eino-examples/devops/visualize" // NewMermaidGeneratorFull Series Document Index
| Document | Content | Position |
|---|---|---|
| Intro Notes | ADK intro + Middleware + Interrupt + Compose overview | 🌱 Intro |
| Agentic Advanced | AgenticModel / AgenticMessage / Typed system / truncation retry | 🌿 Advanced |
| Appendix 1: Flow Module | Flow module: ReAct / Multi-Agent / state graph / Manus / Deer-Go | 🌳 Deep |
| Appendix 2: Components Module | Component module: A/B routing / HTTP logging / retrieval augmentation / document parsing | 🔧 Components |
| Appendix 3: Lambda and Debugging Tools | Lambda writing / Devops debugging / Mermaid visualization | 🛠️ Tools |
📇 Quick-Reference Card for This Appendix
Lambda: InvokableLambda (ctx+T→T) → AppendLambda / AddLambdaNodeDebugging: devops.Init → Compile → test via graphical UIVisualization: NewMermaidGenerator → WithGraphCompileCallbacks → + .pngMessageParser: ChatModel JSON output → Go struct (type-safe handling)📂 Source repo: github.com/cloudwego/eino-examples↗
📖 Keep reading:
- Intro Notes — Eino ADK from Hello World to Compose orchestration
- Agentic Advanced — Responses API / AgenticMessage / Typed generics
- Appendix 1: Flow Module — ReAct Agent / Multi-Agent / state graph
- Appendix 2: Components Module — A/B routing / HTTP logging / retrieval augmentation / document parsing
- Appendix 3: Lambda and Debugging Tools — Lambda writing / Devops / Mermaid visualization ← You are here