Mastering Agentic Systems with Blades: Concepts, Code, and Workflow Patterns
This article explains what an AI Agent is, distinguishes it from traditional workflows, and demonstrates how to build and customize agents using the Go‑based Blades framework, covering core concepts, code examples, five workflow patterns, best‑practice guidelines, and reference resources.
What is an Agent?
In practice an Agent is an autonomous system that can run for extended periods, make decisions, and invoke external tools as needed. It may appear as a goal‑aware, judgment‑capable program or as a rule‑based robot.
Workflow vs. Agent
Workflow follows the traditional software mindset: a predefined sequence of steps organizes the interaction between LLMs and tools, and the logic is fixed by the developer. In short, the workflow controls the model.
Agent emphasizes autonomy and adaptability: the LLM acts as the “brain”, dynamically deciding the next action based on the task goal and current state. In short, the model controls the workflow.
Building Agents with Blades
Blades is a Go framework that provides a concise syntax, high‑concurrency performance, and a plug‑in architecture for extending Agent capabilities while keeping high performance.
Creating an Agent in Blades:
agent, err := blades.NewAgent(
"MyAgent",
blades.WithModel(model),
blades.WithInstruction("You are a helpful assistant."),
blades.WithTools(customTool),
)Defining a custom tool (e.g., a weather query):
// Define weather handling logic
func weatherHandle(ctx context.Context, req WeatherReq) (WeatherRes, error) {
return WeatherRes{Forecast: "Sunny, 25°C"}, nil
}
// Create a weather tool
func createWeatherTool() (tools.Tool, error) {
return tools.NewFunc(
"get_weather",
"Get the current weather for a given city",
weatherHandle,
)
}Using the tool in an Agent:
model := openai.NewModel("deepseek-chat", openai.Config{BaseURL: "https://api.deepseek.com", APIKey: os.Getenv("YOUR_API_KEY")})
agent, err := blades.NewAgent(
"Weather Agent",
blades.WithModel(model),
blades.WithInstruction("You are a helpful assistant that provides weather information."),
blades.WithTools(createWeatherTool()),
)
input := blades.UserMessage("What is the weather in Shanghai City?")
runner := blades.NewRunner(agent)
output, err := runner.Run(context.Background(), input)
log.Println(output.Text())Typical Workflow Patterns
Pattern 1: Chain Workflow (Sequential)
Breaks a complex task into simple, ordered steps. Suitable when steps are clearly defined, each depends on the previous output, and a slight latency increase is acceptable for higher accuracy.
sequentialAgent := flow.NewSequentialAgent(flow.SequentialConfig{
Name: "WritingReviewFlow",
SubAgents: []blades.Agent{writerAgent, reviewerAgent},
})Pattern 2: Parallel Workflow
Allows an LLM to handle multiple independent sub‑tasks simultaneously and then aggregates the results. Ideal for large numbers of similar items, multi‑view analysis, or time‑sensitive tasks.
parallelAgent := flow.NewParallelAgent(flow.ParallelConfig{
Name: "EditorParallelAgent",
Description: "Edits the drafted paragraph in parallel for grammar and style.",
SubAgents: []blades.Agent{editorAgent1, editorAgent2},
})Pattern 3: Routing Workflow
The LLM first classifies the input type and then routes it to the appropriate specialized Agent. Useful when inputs vary widely in structure and require different processing pipelines.
agent, err := flow.NewRoutingAgent(flow.RoutingConfig{
Name: "TriageAgent",
Description: "You determine which agent to use based on the user's homework question",
Model: model,
SubAgents: []blades.Agent{mathTutorAgent, historyTutorAgent},
})Pattern 4: Orchestrator‑Workers
A central LLM (orchestrator) decomposes the task and delegates sub‑tasks to worker Agents. Fits scenarios where tasks cannot be fully predicted in advance and require diverse perspectives.
translatorWorkers := createTranslatorWorkers(model)
orchestratorAgent, _ := blades.NewAgent(
"orchestrator_agent",
blades.WithInstruction(`You are a translation agent. Use the provided tools to translate.`),
blades.WithModel(model),
blades.WithTools(translatorWorkers...),
)Pattern 5: Evaluator‑Optimizer (Loop)
One model generates output, another evaluates it, and feedback drives further iterations—mirroring a "write‑then‑revise" process. Best for tasks with clear quantitative evaluation criteria.
loopAgent := flow.NewLoopAgent(flow.LoopConfig{
Name: "WritingReviewFlow",
Description: "An agent that loops between writing and reviewing until the draft is good.",
MaxIterations: 3,
Condition: func(ctx context.Context, output *blades.Message) (bool, error) {
return !strings.Contains(output.Text(), "The draft is good"), nil
},
SubAgents: []blades.Agent{writerAgent, reviewerAgent},
})Best Practices and Recommendations
Start simple: build a basic workflow before adding complex agents.
Choose the simplest pattern that satisfies the requirement.
Design for reliability: define clear error‑handling, use type‑safe responses, and add validation at each step.
Balance trade‑offs: consider latency versus accuracy and evaluate whether parallelism is appropriate for the scenario.
Reference
https://github.com/go-kratos/blades/blob/main/examples
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Bilibili Tech
Provides introductions and tutorials on Bilibili-related technologies.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
