Journey questions, answered
The draft, the lifecycle, what the agent does and what you do, and the edge cases, answered in plain terms.
The journeys page explains the feature. This page answers the questions people ask once they read the code. None of them are dumb questions; they are the ones almost everyone has.
Is journey.webmcp.ts a journey?
No, and this is the most common confusion. That file never creates a journey. It
is the factory: a reusable createJourney() function that journey files call.
Think of a Lego baseplate and the models built on it. journey.webmcp.ts is the
baseplate, shared and owned by the generator. book-ride.webmcp.ts is a model
someone builds on it. The engine lives in one file; the journeys live elsewhere
and are written per product.
What are the three parts, in plain terms?
- The draft is one plain object in memory, created when the page loads. Steps write into it; the submit reads everything out of it.
- Step tools are ordinary WebMCP tools, one per step
(
book-ride-resolve-destination). When the agent calls one, it does the step's work, stores the result on the draft, and replies "Stored. Still needed: X" or "Stored. The journey is ready." That reply is how the agent knows what to do next. There is no hidden orchestration; the agent works one call at a time and reads the messages. - The submit gate is one final tool (
book-ride-submit) that does four things in order: check nothing is missing and refuse if it is, ask the human to confirm, run the real write with the finished draft, and clear the draft.
Why is it called a "draft"?
Same reason as a draft email. It is the version in progress, built up piece by piece, and nothing is sent until the end. It is a draft because it is not the real thing: nothing reaches your backend from it until the submit runs.
What does "storing something in the draft" actually mean?
Adding a labeled value to that one object, like destination: {...} or
pickupAt: "2026-03-14T19:30:00Z". It is like writing another line on a sticky
note. There is no database, no file, and no network call in the storing itself.
What does "in memory" mean if I am not technical?
Picture a whiteboard in a room versus a filing cabinet down the hall. The whiteboard is right there, fast, and everyone in the room can read it, but the moment the room closes it is gone. The filing cabinet keeps things after everyone leaves. The draft is the whiteboard: it lives only inside the browser tab's running memory. Close the tab, refresh, or navigate away and it is wiped. Nothing durable, ever.
What is the shape of the draft?
The simplest possible: a flat bag of labeled values, for example
{ destination: {...}, pickupAt: "2026-03-14T19:30:00Z" }. Nothing enforces
nesting, and any step can write any field.
Will it hold data reliably for a session?
It depends what you mean by session:
- Within one continuous page view (tab open, agent working, no refresh): yes, completely. It is a variable in memory and nothing drops it mid-flow.
- Across a reload, a closed tab, or a new tab: no, deliberately. It is never meant to outlive one uninterrupted visit.
How does it store results from the real backend?
Not every step touches the backend. A step like set-pickup-time has no logic;
it stores whatever the agent passed in, verbatim, with no network call. A step
like resolve-destination calls the app's real geocoder and stores the real
answer. So the draft ends up holding a mix: some fields are "what the agent
said", some are "what the server said". Either way, nothing is created or
changed for real until the submit.
Why is the draft created only once per page load?
Because createJourney(), the function that sets up the draft, runs once at
page load, not per attempt. There is one shared scratchpad per journey per page
visit. That is fine for the realistic case: one agent, one user, one thing at a
time. The unhandled edge case is two parallel attempts at the same journey on
one page, which would share and overwrite the same draft. Accepted, not handled.
What is a "half-finished journey", and why would it happen?
The agent resolves the destination, then the person closes the laptop or the tab crashes, before the rest of the steps and the submit. Some steps done, nothing sent. Keeping the draft in memory means a reload always starts clean, with no stale, half-filled attempt from three days ago reappearing with an outdated result. Throwing away incomplete progress is the feature, not a gap.
Does a journey reuse the tools codegen already generated?
Yes, directly, and it never reimplements anything. A tool-backed step calls the
same underlying request the standalone tool uses, and the submit's run is the
existing write tool's execute. The journey wraps them with the gate and the
confirmation. Bonus: a risky write like request-ride, normally generated
withheld, never has to be enabled as a standalone tool at all. The journey's
submit becomes its only door, with the prerequisite checks and a human
confirmation built in. Wrapping a risky tool in a journey is a safer way to
expose it than enabling it directly.
How does the agent know these tools exist?
There is no special channel: ordinary WebMCP discovery. On page load, every
registered tool, including journey steps and submits, lands in one flat list the
browser exposes. The agent asks the page what it can do and gets the whole list,
with no formal distinction between a normal tool and part of a journey. The only
grouping signal is in the text: each step's name carries the journey prefix
(book-ride-...), and each description ends with something like "Part of
book-ride: Book a ride to a destination the user gives." The agent reads that
and infers the connection, the same way it figures out anything else. The
factory stitches it mechanically, so it cannot be forgotten.
What does the agent do, and what do I do?
The agent's job is orchestration and conversation: work out what to call next from the replies, and ask the user for anything it cannot get from the backend. Your job is exactly one thing: the final yes or no on the confirmation dialog before anything real happens. The agent cannot click that dialog for you. A human click is the only way through.
Can the agent call the steps out of order?
The order is not enforced by code, so an agent could call set-pickup-time
before resolve-destination. It mostly self-corrects: a step that needs an
earlier step's draft field fails with a readable message naming what is missing,
which nudges the agent back. One honest caveat: that self-correction depends on
the step failing usefully when called early, which is on whoever writes the
journey, not something the shared machinery guarantees.
What happens if I decline the confirmation?
The agent is told "The user declined this action", and the draft is left untouched, not wiped. You can change your mind, adjust something, and submit later without starting over.
Why can't codegen just generate the journeys for me?
Because the flow is not in your API spec. An OpenAPI file says POST /v1/rides
exists; it does not say that booking a ride is really resolve the destination,
then set the pickup time, then confirm. It also cannot know that your product
wants a person to approve the ride rather than let an agent request it
directly. That knowledge lives in the product. A CLI guessing flows produces
plausible-sounding garbage, tools that pass every mechanical check and are still
wrong. So codegen stops at a hint in its report and the bundled skill file
teaches your own coding agent how to write the journey file well. Your agent can
ask you about the product; the CLI cannot.
Won't journeys make my tool list even bigger?
They can, if you let them. verify counts journey tools in the surface total,
one per step plus the submit gate, and warns when the whole surface grows past
what is good for agents. It is a warning, not a failed build: the browser has no
limit on how many tools you register, only agent quality does.
Keeping the surface small is a convention you follow, not something the
generator does for you. A read tool that a journey uses still registers on its
own, so if it only makes sense inside the flow, withhold it in
.webmcp-codegen.json or exclude it with safety.exclude. Writes reachable
through a journey submit stay withheld as standalone tools unless you enable
them, so leave them withheld and the submit is their only door.
What if two steps use the same draft field name?
The second overwrites the first, silently. The draft is a flat bag with no protection, so give each step's fields distinct names when you write the journey.
Journeys
A few steps that share state, ending in one write a person confirms. Journeys are how you describe a goal that takes more than one tool call.
Working with your coding agent
The generator writes the parts an API can describe. Your own agent writes the parts that need product knowledge, including journeys. Here is how to ask it.