Files
micro--go-micro/internal/website/blog/18.md
T
wehub-resource-sync e071084ebe
govulncheck / govulncheck (push) Has been cancelled
Lint / golangci-lint (push) Has been cancelled
Run Tests / Unit Tests (push) Has been cancelled
Run Tests / Etcd Integration Tests (push) Has been cancelled
Harness (E2E) / Harnesses (mock LLM) (push) Has been cancelled
Harness (E2E) / Provider harnesses (live LLM conformance) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:40:33 +08:00

94 lines
5.7 KiB
Markdown

---
layout: blog
title: "Not Everything Should Be an Agent"
permalink: /blog/18
description: "We spent two posts on agents that plan and delegate. Here's the other half: when the path is known, you want a workflow — predictable, event-driven, deterministic. In Go Micro they're the same building blocks, two modes."
---
# Not Everything Should Be an Agent
*June 8, 2026 • By the Go Micro Team*
The last two posts were about agents — [the abstraction](/blog/16), and then [agents that plan and delegate](/blog/17), directing their own work over many turns. That's the exciting part. It's also, honestly, the part you should reach for *least often*.
An agent decides its own path at runtime. That's powerful when the task genuinely needs it, and a liability when it doesn't — you trade predictability, latency, and cost for flexibility you may not want. Most real work has a known shape: *when this event happens, do these things.* For that, you don't want a model improvising. You want a **workflow**.
The distinction is the one Anthropic draws in [Building Effective Agents](https://www.anthropic.com/engineering/building-effective-agents): a **workflow** is LLMs and tools orchestrated through *predefined* paths; an **agent** is an LLM *dynamically directing* its own process. Determinism is the dividing line. Go Micro has both — and they're the same building blocks underneath.
## A workflow is a Flow
In Go Micro, the predefined-path side is a `Flow`. It subscribes to an event and runs one defined step: a prompt, with your services available as tools.
```go
f := micro.NewFlow("onboard-user",
micro.FlowTrigger("events.user.created"),
micro.FlowPrompt("New user {{.Data}} — create a workspace and send a welcome email."),
micro.FlowProvider("anthropic"),
)
```
When a `user.created` event lands on the broker, the flow fires. There's no open-ended loop, no self-direction — a known trigger runs a known step. You can read exactly what it will do. That's the point.
## Same building blocks, two modes
Here's what makes this coherent rather than two competing systems: a workflow and an agent are built from the *same* primitive — the augmented LLM. A model, with every service endpoint already available as a tool, and the store as memory. Go Micro gives you that for free; every endpoint is a tool the moment a service registers.
The only difference is **who decides the path**:
- **You decide it** → a workflow (`Flow`). The trigger and the step are fixed.
- **The model decides it** → an agent (`Agent`). It plans, calls tools, evaluates, and chooses the next step.
It's not two frameworks. It's one set of pieces, pointed two ways.
## Flow triggers, Agent reasons
Sometimes a workflow's step genuinely needs judgment — the path isn't fully knowable in advance. You don't have to choose globally. A flow can *hand off* to an agent: the workflow stays the deterministic trigger, and the agent does the open-ended part.
```go
f := micro.NewFlow("onboard-user",
micro.FlowTrigger("events.user.created"),
micro.FlowPrompt("New user {{.Data}} — get them set up."),
micro.FlowAgent("conductor"), // the flow triggers; the conductor agent reasons
)
```
Now the event fires the flow, the flow renders the prompt, and a registered `conductor` agent handles it over RPC — with its full toolkit: [plan, delegate](/blog/17), memory, and guardrails. **Flow triggers, Agent reasons.** The deterministic and dynamic halves compose along one clean seam, because an agent is just a service and the hand-off is just an RPC.
## Predictability, even in agents
Choosing an agent doesn't mean giving up control. Anthropic is emphatic that autonomous agents need stopping conditions and human checkpoints, and Go Micro's agent has both — as plain options, not a framework:
```go
micro.NewAgent("conductor",
micro.AgentServices("task"),
micro.AgentMaxSteps(8), // a stopping condition
micro.AgentApproveTool(approveBilling), // a human-in-the-loop gate
)
```
`MaxSteps` bounds how many actions the agent may take. `ApproveTool` gates each action before it runs — return `false` and it's blocked, with the reason fed back to the model. These are guardrails: a counter and a callback on the path every tool call already takes. No new abstraction.
## Which one do you reach for?
The honest order, smallest first:
1. **A single model call.** Most tasks need nothing more — one augmented LLM, one service call. Start here.
2. **A workflow (`Flow`).** When the path is well-defined and you want it to be predictable and event-driven.
3. **An agent (`Agent`).** When the task genuinely needs flexibility and model-driven decisions — and you accept the cost, and add the guardrails.
The mistake is starting at 3. Agents are the most capable tool and the easiest to over-apply. Reach for the simplest thing that does the job, and move up only when the job demands it.
## One set of pieces
We didn't build a workflow engine and an agent framework. We built services that are tools, and then pointed an LLM at them two ways — a predefined path, or a dynamic one. `Flow` and `Agent` are modes, not frameworks, and they compose because they share everything underneath. That's the same principle we've held since [going all in on AI](/blog/14): services are the only abstraction, the LLM calls them as tools, and everything else is how you arrange them.
Read the [Agents and Workflows guide](/docs/guides/agents-and-workflows) for the full mapping, or [Plan & Delegate](/docs/guides/plan-delegate) for the agent side.
```bash
curl -fsSL https://go-micro.dev/install.sh | sh
```
---
*Go Micro is open source. Star us on [GitHub](https://github.com/micro/go-micro), join the [Discord](https://discord.gg/G8Gk5j3uXr), or read the [docs](https://go-micro.dev/docs).*