From 0795ca30b0cf61466e4cf0f26c527f21ade1d887 Mon Sep 17 00:00:00 2001 From: IPender Date: Wed, 12 Nov 2025 17:07:23 +0800 Subject: [PATCH] feat(adk): add Exit tool for loop_for_reflection (#127) * feat(adk): add Exit tool for loop_for_reflection * feat(adk): add break_loop event for loop_for_reflection * feat(adk): add break_loop event for loop_for_reflection --- .../workflow/loop/loop_for_reflection.go | 8 +++-- .../workflow/loop/subagents/chatmodel.go | 35 ++++++++++++++++--- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/adk/intro/workflow/loop/loop_for_reflection.go b/adk/intro/workflow/loop/loop_for_reflection.go index 746ec58..ddf589a 100644 --- a/adk/intro/workflow/loop/loop_for_reflection.go +++ b/adk/intro/workflow/loop/loop_for_reflection.go @@ -20,11 +20,12 @@ import ( "context" "fmt" "log" + "time" - "github.com/cloudwego/eino-examples/adk/common/trace" "github.com/cloudwego/eino/adk" "github.com/cloudwego/eino-examples/adk/common/prints" + "github.com/cloudwego/eino-examples/adk/common/trace" "github.com/cloudwego/eino-examples/adk/intro/workflow/loop/subagents" ) @@ -35,7 +36,7 @@ func main() { defer traceCloseFn(ctx) a, err := adk.NewLoopAgent(ctx, &adk.LoopAgentConfig{ - Name: "ReflectionAgent", + Name: "reflection_agent", Description: "Reflection agent with main and critique agent for iterative task solving.", SubAgents: []adk.Agent{subagents.NewMainAgent(), subagents.NewCritiqueAgent()}, MaxIterations: 5, @@ -45,7 +46,7 @@ func main() { } query := "briefly introduce what a multimodal embedding model is." - ctx, endSpanFn := startSpanFn(ctx, "layered-supervisor", query) + ctx, endSpanFn := startSpanFn(ctx, "ReflectionAgents", query) runner := adk.NewRunner(ctx, adk.RunnerConfig{ EnableStreaming: true, // you can disable streaming here @@ -73,4 +74,5 @@ func main() { } endSpanFn(ctx, lastMessage) + time.Sleep(20 * time.Second) } diff --git a/adk/intro/workflow/loop/subagents/chatmodel.go b/adk/intro/workflow/loop/subagents/chatmodel.go index bdd6139..d72127a 100644 --- a/adk/intro/workflow/loop/subagents/chatmodel.go +++ b/adk/intro/workflow/loop/subagents/chatmodel.go @@ -21,13 +21,16 @@ import ( "log" "github.com/cloudwego/eino/adk" + "github.com/cloudwego/eino/components/tool" + "github.com/cloudwego/eino/components/tool/utils" + "github.com/cloudwego/eino/compose" "github.com/cloudwego/eino-examples/adk/common/model" ) func NewMainAgent() adk.Agent { a, err := adk.NewChatModelAgent(context.Background(), &adk.ChatModelAgentConfig{ - Name: "MainAgent", + Name: "main_agent", Description: "Main agent that attempts to solve the user's task.", Instruction: `You are the main agent responsible for solving the user's task. Provide a comprehensive solution based on the given requirements. @@ -41,18 +44,40 @@ Focus on delivering accurate and complete results.`, } func NewCritiqueAgent() adk.Agent { + + exitAndSummarizeTool, err := utils.InferTool("exit_and_summarize", "exit from the loop and provide a final summary response", + func(ctx context.Context, req *exitAndSummarize) (string, error) { + _ = adk.SendToolGenAction(ctx, "exit_and_summarize", adk.NewBreakLoopAction("critique_agent")) + return req.Summary, nil + }) + if err != nil { + log.Fatalf("create tool failed, name=%v, err=%v", "exit_and_summarize", err) + } a, err := adk.NewChatModelAgent(context.Background(), &adk.ChatModelAgentConfig{ - Name: "CritiqueAgent", + Name: "critique_agent", Description: "Critique agent that reviews the main agent's work and provides feedback.", Instruction: `You are a critique agent responsible for reviewing the main agent's work. Analyze the provided solution for accuracy, completeness, and quality. If you find issues or areas for improvement, provide specific feedback. -If the work is satisfactory, call the 'exit' tool and provide a final summary response.`, +If the work is satisfactory, call the 'exit_and_summarize' tool and provide a final summary response.`, Model: model.NewChatModel(), - // Exit: nil, // use default exit tool + ToolsConfig: adk.ToolsConfig{ + ToolsNodeConfig: compose.ToolsNodeConfig{ + Tools: []tool.BaseTool{ + exitAndSummarizeTool, + }, + }, + ReturnDirectly: map[string]bool{ + "exit_and_summarize": true, + }, + }, }) if err != nil { - log.Fatal(err) + log.Fatalf("create agent failed, name=%v, err=%v", "critique_agent", err) } return a } + +type exitAndSummarize struct { + Summary string `json:"summary" jsonschema_description:"final summary of the solution"` +}