This page is for the code path - wiring events, webhooks, credentials and MCP by hand. To build an
agent without code, start with Build your first agent.
An agent is only useful if something real can start it and something real happens when it finishes.
You do not have to change how your business emits work to get either: a run starts from whatever you
already have, and the result leaves the same way. Both directions keep a durable attempt log you can
inspect, redeliver, or replay, so “did the partner ever get it?” is a question with an answer.
Getting a run started
Pick whichever you already have; a workflow can be started by more than one.
Getting the result out
An agent can drive all of it
Duraton ships an MCP server, so an AI agent is a first-class operator: it
can list and control runs, send events, and decide approvals. An agent is
not only the thing being run; it can be the thing doing the running. The same server, and llms.txt,
are how you point a coding assistant at these docs and your project.
What each inbound transport guarantees
Every transport ships a capability descriptor you can read from the engine, generated from the same
closed sets the API serves. A webhook source is the only transport today, so nothing differs - the
descriptor exists so that when a second one lands, its differences are stated rather than implied
away.
Ordering is two questions, not one
A transport’s ordering is not an ordering your runs keep. A broker that guarantees delivery
order within a partition or a queue says nothing about execution order: Duraton does not preserve
ordering past ingest, because runs are admitted from a queue sorted on when they are due, with no
creation-order tiebreak, and a concurrency key buys mutual exclusion rather than sequence.
That is why the descriptor carries two fields. ordering is what the transport promises on the
way in; runOrdering is what survives, and it is none for every transport today. Reading the first
without the second is the mistake this section exists to prevent: a true fact about your broker reads
as a promise about your workflows.
If your workload needs records for one key handled in order, ordering at the transport is not enough.
Model it explicitly: one workflow that processes a batch in order, or a state machine keyed on the
entity, rather than assuming per-partition delivery becomes per-partition execution.
Acknowledgement is what makes durability possible
The promise is that work triggered by a message actually finishes. That rests on being able to tell
the transport a message was handled, and on not telling it when the message was not.
- Synchronous (webhooks): the HTTP status is the acknowledgement. There is nothing to acknowledge
later, so a sender that gives up is the end of it. That is why an inbound delivery is recorded and
can be replayed.
A transport that acknowledges nothing cannot carry the promise honestly. Redis pub/sub and MQTT
QoS 0 are fire-and-forget: nothing is retained, nothing is replayed, and a consumer that was not
listening simply missed the message. Duraton does not offer them as sources rather than accepting
them and quietly delivering a weaker guarantee under the same name.
Where a dedupe id comes from
A dedupe id is what makes a redelivery a no-op rather than a second run. There is no universal
formula for it, and the descriptor says so per transport:
- A webhook has no identifier that is stable across redelivery, so there is no default: a source
that wants dedupe names a key to read from the payload or a header.
Both are overridable with a template. The default is the transport’s to declare, because it depends
on what that transport actually keeps stable. A RabbitMQ delivery tag, for instance, is scoped to a
channel and is not stable across redelivery, so it could never serve as one.
- Webhooks - inbound sources, outbound subscriptions, signing, and the attempt log.
- Credentials - stored credentials a step resolves at run time.
- MCP server - what an agent can do to Duraton, and how to connect one.