---
layout: blog
title: "When the Event Is the Prompt"
permalink: /blog/21
description: "Most agents wait for a human to type something. The useful ones don't — they run because something happened in the system. A Flow turns an event into the prompt, and an agent acts on its own."
---

# When the Event Is the Prompt

*June 15, 2026 &bull; Asim Aslam*

Almost every agent demo starts the same way: a human types a prompt, the agent responds. That framing is a habit from chat, and it hides the more useful case. The agents worth running don't wait for you to ask. They run because something happened — a user signed up, a payment failed, a deployment finished, a metric crossed a line. In those systems there is no prompt, because there is no human in the loop. The event is the prompt.

Go Micro has had the pieces for this since we added [workflows](/blog/18): a `Flow` subscribes to a broker topic, and an `Agent` reasons and acts. Putting them together is the point of this post.

## The shape

A workflow is the deterministic half — it knows *when* to run (an event arrives) and turns that event into a prompt. An agent is the dynamic half — it decides *what to do* about it. Connect them and you get an agent that runs on events, unattended.

```go
// The agent: it onboards new users using its services.
onboarder := micro.NewAgent("onboarder",
    micro.AgentServices("workspace", "notify"),
    micro.AgentPrompt("You onboard new users. Create their workspace and send a welcome."),
    micro.AgentProvider("anthropic"),
)
go onboarder.Run()

// The workflow: when a user signs up, hand the event to the agent.
f := micro.NewFlow("onboard",
    micro.FlowTrigger("events.user.created"),
    micro.FlowPrompt("A new user signed up: {{.Data}}. Get them set up."),
    micro.FlowAgent("onboarder"),
)
```

When a `user.created` event lands on the broker, the flow renders it into a prompt and hands it to the onboarder over RPC. The agent looks at its tools, creates the workspace, sends the welcome, and stops. No one typed anything.

There's a runnable version of exactly this in [`internal/harness/agent-flow`](https://github.com/micro/go-micro/tree/master/internal/harness/agent-flow) — real services, registry, RPC, broker, and the agent loop, with only the model mocked so it runs without a key:

```
> event: publishing events.user.created {"email":"alice@acme.com"}

  [onboarder] → workspace_WorkspaceService_Create({"owner":"alice@acme.com"})
    [workspace] created ws-1 for alice@acme.com
  [onboarder] → notify_NotifyService_Send({"to":"alice@acme.com","message":"Welcome — your workspace is ready."})
    [notify] 📨 to=alice@acme.com message="Welcome — your workspace is ready."

✓ the agent onboarded the user — triggered by an event, not a prompt
```

## This is where microagents become real

A chat agent is something you visit. An event-driven agent is something that runs. That difference is what makes [an agent for everything](/blog/20) practical: each domain gets a small agent that wakes on its own events and acts. Payments has an agent that responds to failed charges. Ops has one that reacts to alerts. Support has one that triages new tickets. None of them is a monolithic brain holding the whole system in one context; each is scoped, each runs on its events, and they reach each other over RPC when they need to. It's the microservices decomposition, applied to the intelligence.

The mechanics are already there: an agent is a service, agents call each other with `delegate`, and a flow is the trigger. The only thing that changed is the absence of a person at the start of the loop.

## What running unattended demands

Taking the human out of the loop raises the bar, and it's worth being honest about that rather than pretending it's free.

- **Guardrails stop being optional.** When you're sitting in a chat you are the stopping condition — you see a wrong turn and intervene. An event-driven agent has no one watching, so the bounds have to be in the code: `MaxSteps` to cap what it can do per event, and `ApproveTool` to gate the actions that genuinely need a human or a policy check. For an unattended agent these are load-bearing, not nice-to-haves.
- **Observability becomes the interface.** If no one is reading the agent's replies, the trace of what it did is the only way to know it did the right thing. The reply text matters less than a record of the tools it called and the results it got.
- **Execution has to be durable.** An event-driven agent may run longer than a request, and it has to survive a restart without dropping the work or repeating it. Its memory is already store-backed and durable; the loop itself needs to be checkpointed and resumable in the same way.

The first of these is shipped today. The other two are the next things to build, and they're the same gaps the [last post](/blog/20) named — autonomy is what makes them urgent.

## Three primitives, one substrate

This is the whole picture coming together:

- a **service** is a capability;
- an **agent** is intelligence pointed at capabilities;
- a **workflow** is the trigger — and when the trigger is an event, it is also the prompt.

You compose them. A workflow turns an event into a prompt, an agent reasons about it, services do the work, and other agents pick up the parts they own. The human moves from typing every instruction to setting the system up and letting it run. That is the shift worth building for: not better chat, but software that acts on its own — on the same services, agents, and workflows you already have.
