Skip to content

Commit 94ddd6c

Browse files
authored
Merge pull request #253 from go-kratos/blog/Building-Effective-Agents
feat: add building-effective-agents blog
2 parents 59a4dd3 + a7b543e commit 94ddd6c

File tree

7 files changed

+544
-0
lines changed

7 files changed

+544
-0
lines changed
-53.4 KB
Loading
14.1 KB
Loading
18.5 KB
Loading
-66.6 KB
Loading
14.4 KB
Loading
Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
---
2+
title: A New Paradigm for Agent Development: Efficient Agent & Workflow Practices under the Blades Architecture
3+
description: This article introduces how to understand and build Agents within the Blades framework, and explains various workflow design patterns in detail, helping developers choose the appropriate architectural solution based on business needs.
4+
keywords:
5+
- AI
6+
- Agent
7+
- Blades
8+
- Workflow
9+
tags: [Blades, Agent]
10+
---
11+
## What is an Agent?
12+
There is no unified, strict definition of **Agent** in the industry. Descriptions of Agents vary slightly among different vendors, open-source communities, and even academic papers. However, overall, an Agent typically refers to **an intelligent system capable of long-term autonomous operation, possessing certain decision-making abilities, and able to call various external tools as needed by the task**.
13+
14+
It can manifest as a program that "understands goals, makes judgments, and executes actions," or it can be a traditional **rule-based fixed-process robot**.
15+
16+
In Blades, we collectively refer to these different forms as **Agentic Systems**. Although they all fall under the category of Agents, when designing the actual architecture, it is essential to distinguish between two core concepts: **Workflow** and **Agent**.
17+
18+
### Workflow
19+
Workflow leans more towards traditional software thinking: it relies on **predefined execution steps** to organize the calling relationships between LLMs and tools. All logical sequences are planned in advance and hardcoded into flowcharts or code.
20+
21+
Characteristics:
22+
- The execution path is **fixed** and predictable
23+
- The inputs, outputs, and conditional branches for each step are predetermined by the developer
24+
- More suitable for tasks with standardized, stable, and decomposable business processes
25+
- Easy to control boundaries, test, and audit
26+
27+
In a nutshell: **The model follows the process, rather than the process adapting to the model.**
28+
29+
### Agent
30+
The core value of an Agent lies in its "autonomy" and "adaptability." It does not run according to a flowchart; instead, it uses the LLM as the "brain" to **dynamically decide the next step** based on the task objective and current state.
31+
32+
Typical capabilities of an Agent include:
33+
- The LLM **autonomously decides** the execution steps, rather than relying on a preset process
34+
- Capable of autonomously selecting, combining, or making multiple calls to external tools
35+
- Possesses "memory" and "understanding" of the global task state during execution
36+
- Dynamically changes strategy based on real-time feedback, rather than following fixed branches
37+
- In some cases, it can run continuously, similar to a "service-type Agent"
38+
39+
Therefore, compared to a Workflow, an Agent is closer to an **active executor** rather than a passive process node.
40+
41+
In a nutshell: **A Workflow is "the process controlling the model," whereas an Agent is "the model controlling the process."**
42+
43+
### Building with Blades: Agent
44+
45+
Leveraging Go's concise syntax and high concurrency features, Blades provides a flexible and extensible Agent architecture. Its design philosophy is to enable developers to easily extend Agent capabilities while maintaining high performance through unified interfaces and pluggable components.
46+
The overall architecture is as follows:
47+
48+
![architecture](/images/architecture.png)
49+
50+
In **Blades**, you can create an Agent using `blades.NewAgent`. The Agent is the core component of the framework, primarily responsible for:
51+
52+
- Calling the LLM model
53+
- Managing tools
54+
- Executing prompts
55+
- Controlling the entire task execution flow
56+
57+
Simultaneously, Blades provides an elegant and straightforward way to customize tools using `tools.NewTool` or `tools.NewFunc`, allowing the Agent to access external APIs, business logic, or computational capabilities.
58+
59+
Here is an example of a custom weather query tool:
60+
61+
```go
62+
// Define weather handling logic
63+
func weatherHandle(ctx context.Context, req WeatherReq) (WeatherRes, error) {
64+
return WeatherRes{Forecast: "Sunny, 25°C"}, nil
65+
}
66+
// Create a weather tool
67+
func createWeatherTool() (tools.Tool, error) {
68+
return tools.NewFunc(
69+
"get_weather",
70+
"Get the current weather for a given city",
71+
weatherHandle,
72+
)
73+
}
74+
```
75+
76+
Then build a smart assistant (Weather Agent) capable of calling the weather tool:
77+
78+
```go
79+
// Configure the model to call and its address
80+
model := openai.NewModel("deepseek-chat", openai.Config{
81+
BaseURL: "https://api.deepseek.com",
82+
APIKey: os.Getenv("YOUR_API_KEY"),
83+
})
84+
// Create a Weather Agent
85+
agent, err := blades.NewAgent(
86+
"Weather Agent",
87+
blades.WithModel(model),
88+
blades.WithInstruction("You are a helpful assistant that provides weather information."),
89+
blades.WithTools(createWeatherTool()),
90+
)
91+
if err != nil {
92+
log.Fatal(err)
93+
}
94+
// Query the weather information for Shanghai
95+
input := blades.UserMessage("What is the weather in Shanghai City?")
96+
runner := blades.NewRunner(agent)
97+
output, err := runner.Run(ctx := context.Background(), input)
98+
if err != nil {
99+
log.Fatal(err)
100+
}
101+
log.Println(output.Text())
102+
```
103+
104+
With Blades' framework design, you can quickly build an Agent capable of both calling tools and making autonomous decisions with just a small amount of code.
105+
106+
Next, we will introduce several typical workflow patterns based on the Blades framework. Each design pattern is suitable for different business scenarios, ranging from the simplest linear flows to highly autonomous Agents. You can choose the appropriate design method according to your actual business needs.
107+
108+
## Pattern 1: Chain Workflow
109+
110+
This pattern embodies the principle of "breaking down complex tasks into simple steps."
111+
Applicable scenarios:
112+
113+
- The task itself has clear, sequential steps.
114+
- Willing to sacrifice a little latency for higher accuracy.
115+
- Each step depends on the output of the previous step.
116+
117+
![](/images/blades/chain-workflow.png)
118+
119+
Example code (examples/workflow-sequential):
120+
```go
121+
// Sequential workflow, executing agents according to the arranged order
122+
sequentialAgent := flow.NewSequentialAgent(flow.SequentialConfig{
123+
Name: "WritingReviewFlow",
124+
SubAgents: []blades.Agent{
125+
writerAgent,
126+
reviewerAgent,
127+
},
128+
})
129+
```
130+
131+
## Pattern 2: Parallelization Workflow
132+
133+
This pattern is used to have the LLM process multiple subtasks simultaneously and then aggregate the results.
134+
135+
Applicable scenarios:
136+
- Need to process a large number of "similar but independent" items.
137+
- The task requires multiple different perspectives.
138+
- Time-sensitive and the task can be parallelized.
139+
140+
![](/images/blades/parallel-workflow.png)
141+
142+
Example code (examples/workflow-parallel):
143+
```go
144+
// Parallel workflow, storing generated results in the session state for reference by subsequent processes
145+
parallelAgent := flow.NewParallelAgent(flow.ParallelConfig{
146+
Name: "EditorParallelAgent",
147+
Description: "Edits the drafted paragraph in parallel for grammar and style.",
148+
SubAgents: []blades.Agent{
149+
editorAgent1,
150+
editorAgent2,
151+
},
152+
})
153+
// Define a sequential workflow, incorporating the parallel definition
154+
sequentialAgent := flow.NewSequentialAgent(flow.SequentialConfig{
155+
Name: "WritingSequenceAgent",
156+
Description: "Drafts, edits, and reviews a paragraph about climate change.",
157+
SubAgents: []blades.Agent{
158+
writerAgent,
159+
parallelAgent,
160+
reviewerAgent,
161+
},
162+
})
163+
```
164+
This pattern can significantly improve throughput, but be mindful of the resource consumption and complexity introduced by parallelism.
165+
166+
## Pattern 3: Routing Workflow
167+
168+
This pattern uses the LLM to intelligently judge the input type and then dispatches it to different processing flows.
169+
Applicable scenarios:
170+
- Multiple input categories with significant structural differences.
171+
- Different input types require specialized processing flows.
172+
- High classification accuracy is achievable.
173+
174+
![](/images/blades/routing-workflow.png)
175+
176+
Example code (examples/workflow-routing):
177+
```go
178+
// Automatically selects the appropriate expert agent based on the Agent's description
179+
agent, err := flow.NewRoutingAgent(flow.RoutingConfig{
180+
Name: "TriageAgent",
181+
Description: "You determine which agent to use based on the user's homework question",
182+
Model: model,
183+
SubAgents: []blades.Agent{
184+
mathTutorAgent,
185+
historyTutorAgent,
186+
},
187+
})
188+
```
189+
190+
## Pattern 4: Orchestrator-Workers
191+
192+
This pattern combines the "Agent" tendency: a central LLM acts as a task decomposer (orchestrator), and different "Workers" execute the subtasks.
193+
194+
Applicable scenarios:
195+
- Cannot fully predict subtasks in advance.
196+
- The task requires multiple perspectives or processing methods.
197+
- Requires system adaptability and complex decision-making processes.
198+
199+
![](/images/blades/orchestrator-workers.png)
200+
201+
Example code (examples/workflow-orchestrator):
202+
```go
203+
// Define translators via tools (Agent as a Tool)
204+
translatorWorkers := createTranslatorWorkers(model)
205+
// The orchestrator selects and executes the required tools
206+
orchestratorAgent, err := blades.NewAgent(
207+
"orchestrator_agent",
208+
blades.WithInstruction(`You are a translation agent. You use the tools given to you to translate.
209+
If asked for multiple translations, you call the relevant tools in order.
210+
You never translate on your own, you always use the provided tools.`),
211+
blades.WithModel(model),
212+
blades.WithTools(translatorWorkers...),
213+
)
214+
// Synthesize the multiple generated results
215+
synthesizerAgent, err := blades.NewAgent(
216+
"synthesizer_agent",
217+
blades.WithInstruction("You inspect translations, correct them if needed, and produce a final concatenated response."),
218+
blades.WithModel(model),
219+
)
220+
```
221+
222+
## Pattern 5: Evaluator-Optimizer
223+
224+
In this pattern, one model generates output, and another model evaluates that output and provides feedback, mimicking the human "write then revise" process.
225+
Applicable scenarios:
226+
- There are clear, quantifiable evaluation criteria.
227+
- Quality can be significantly improved through multiple rounds of "generate → evaluate → improve".
228+
- The task is suitable for iterative refinement.
229+
230+
![](/images/blades/evaluator-optimizer.png)
231+
232+
Example code (examples/workflow-loop):
233+
```go
234+
// Iterates multiple times by generating content and then evaluating the effect
235+
loopAgent := flow.NewLoopAgent(flow.LoopConfig{
236+
Name: "WritingReviewFlow",
237+
Description: "An agent that loops between writing and reviewing until the draft is good.",
238+
MaxIterations: 3,
239+
Condition: func(ctx context.Context, output *blades.Message) (bool, error) {
240+
// Evaluate content effectiveness to determine whether to end the iteration
241+
return !strings.Contains(output.Text(), "The draft is good"), nil
242+
},
243+
SubAgents: []blades.Agent{
244+
writerAgent,
245+
reviewerAgent,
246+
},
247+
})
248+
```
249+
250+
## Best Practices and Recommendations
251+
252+
In business practice, whether for a single agent or a multi-agent architecture, engineering design often determines the final outcome more than model capability.
253+
254+
The following practical recommendations summarize the most critical principles from real projects and can serve as a reference when designing and implementing agents.
255+
256+
Start Simple
257+
- Build a basic workflow first, then consider more complex agents.
258+
- Use the simplest pattern that meets the requirements.
259+
260+
Design for Reliability
261+
- Define clear error handling mechanisms.
262+
- Strive to use type-safe responses.
263+
- Add validation at every step.
264+
265+
Trade-offs
266+
- Balance latency against accuracy.
267+
- Evaluate the scenario before deciding on parallelism.
268+
269+
## Reference
270+
https://github.com/go-kratos/blades/blob/main/examples

0 commit comments

Comments
 (0)