--- 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/WeMU5AGxD), or read the [docs](https://go-micro.dev/docs).*