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.
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.
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.
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.
Characteristics:
In a nutshell: The model follows the process, rather than the process adapting to the model.
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.
Typical capabilities of an Agent include:
Therefore, compared to a Workflow, an Agent is closer to an active executor rather than a passive process node.
In a nutshell: A Workflow is “the process controlling the model,” whereas an Agent is “the model controlling the process.”
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. The overall architecture is as follows:

In Blades, you can create an Agent using blades.NewAgent. The Agent is the core component of the framework, primarily responsible for:
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.
Here is an example of a custom weather query tool:
// Define weather handling logicfunc weatherHandle(ctx context.Context, req WeatherReq) (WeatherRes, error) { return WeatherRes{Forecast: "Sunny, 25°C"}, nil}// Create a weather toolfunc createWeatherTool() (tools.Tool, error) { return tools.NewFunc( "get_weather", "Get the current weather for a given city", weatherHandle, )}Then build a smart assistant (Weather Agent) capable of calling the weather tool:
// Configure the model to call and its addressmodel := openai.NewModel("deepseek-chat", openai.Config{ BaseURL: "https://api.deepseek.com", APIKey: os.Getenv("YOUR_API_KEY"),})// Create a Weather Agentagent, err := blades.NewAgent( "Weather Agent", blades.WithModel(model), blades.WithInstruction("You are a helpful assistant that provides weather information."), blades.WithTools(createWeatherTool()),)if err != nil { log.Fatal(err)}// Query the weather information for Shanghaiinput := blades.UserMessage("What is the weather in Shanghai City?")runner := blades.NewRunner(agent)output, err := runner.Run(context.Background(), input)if err != nil { log.Fatal(err)}log.Println(output.Text())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.
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.
This pattern embodies the principle of “breaking down complex tasks into simple steps.” Applicable scenarios:

Example code (examples/workflow-sequential):
// Sequential workflow, executing agents according to the arranged ordersequentialAgent := flow.NewSequentialAgent(flow.SequentialConfig{ Name: "WritingReviewFlow", SubAgents: []blades.Agent{ writerAgent, reviewerAgent, },})This pattern is used to have the LLM process multiple subtasks simultaneously and then aggregate the results.
Applicable scenarios:

Example code (examples/workflow-parallel):
// Parallel workflow, storing generated results in the session state for reference by subsequent processesparallelAgent := flow.NewParallelAgent(flow.ParallelConfig{ Name: "EditorParallelAgent", Description: "Edits the drafted paragraph in parallel for grammar and style.", SubAgents: []blades.Agent{ editorAgent1, editorAgent2, },})// Define a sequential workflow, incorporating the parallel definitionsequentialAgent := flow.NewSequentialAgent(flow.SequentialConfig{ Name: "WritingSequenceAgent", Description: "Drafts, edits, and reviews a paragraph about climate change.", SubAgents: []blades.Agent{ writerAgent, parallelAgent, reviewerAgent, },})This pattern can significantly improve throughput, but be mindful of the resource consumption and complexity introduced by parallelism.
This pattern uses the LLM to intelligently judge the input type and then dispatches it to different processing flows. Applicable scenarios:

Example code (examples/workflow-routing):
// Automatically selects the appropriate expert agent based on the Agent's descriptionagent, 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, },})This pattern combines the “Agent” tendency: a central LLM acts as a task decomposer (orchestrator), and different “Workers” execute the subtasks.
Applicable scenarios:

Example code (examples/workflow-orchestrator):
// Define translators via tools (Agent as a Tool)translatorWorkers := createTranslatorWorkers(model)// The orchestrator selects and executes the required toolsorchestratorAgent, err := blades.NewAgent( "orchestrator_agent", blades.WithInstruction(`You are a translation agent. You use the tools given to you to translate. If asked for multiple translations, you call the relevant tools in order. You never translate on your own, you always use the provided tools.`), blades.WithModel(model), blades.WithTools(translatorWorkers...),)// Synthesize the multiple generated resultssynthesizerAgent, err := blades.NewAgent( "synthesizer_agent", blades.WithInstruction("You inspect translations, correct them if needed, and produce a final concatenated response."), blades.WithModel(model),)In this pattern, one model generates output, and another model evaluates that output and provides feedback, mimicking the human “write then revise” process. Applicable scenarios:

Example code (examples/workflow-loop):
// Iterates multiple times by generating content and then evaluating the effectloopAgent := 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) { // Evaluate content effectiveness to determine whether to end the iteration return !strings.Contains(output.Text(), "The draft is good"), nil }, SubAgents: []blades.Agent{ writerAgent, reviewerAgent, },})In business practice, whether for a single agent or a multi-agent architecture, engineering design often determines the final outcome more than model capability.
The following practical recommendations summarize the most critical principles from real projects and can serve as a reference when designing and implementing agents.
Start Simple
Design for Reliability
Trade-offs