Agent / Expose, do not reimplement

What an agent may do: expose Messages

AgentBuilder.expose(Message, ...) selects application Message variants and gives them protocol-facing metadata.

That is the core safety property of the package: the agent cannot invent a new transition path around the application. It can only request transitions already represented in the Message union and already handled by update.

Expose intents, not facts

Suppose creating a todo requires generating an id:

RequestedTodo
    |
    | update starts Command
    v
Command generates id + timestamp
    |
    v
SubmittedTodo { id, title, createdAt }

The agent should normally expose RequestedTodo, not SubmittedTodo. SubmittedTodo is a fact whose id and timestamp were minted by application logic. Letting an agent manufacture it would move nondeterminism and invariants out of the state machine and into the protocol boundary.

Mapped input makes that explicit:

ts
RequestedTodo: Agent.variant({
  name: 'add_todo',
  description: 'Add a todo with the given title',
  input: Schema.Struct({ title: Schema.String }),
  toMessage: ({ title }) => ({ title }),
})

The external tool schema can therefore be simpler than the eventual durable fact, and decoding happens before a Message is constructed.