defineEvent
Function, in src/define-event.ts of @jr2/agent-protocol, a dependency of @jr2/orchestrator. It is an export of @jr2/orchestrator, on the Authoring surface page, in Machine and events.
function defineEvent<const Name extends string, Input extends z.ZodObject>(def: {
name: Name;
description?: string;
input: Input;
semantics?: EventSemantics;
audience?: EventAudience;
}): EventDef<Name, Input>Define one workflow event: an event that an Agent or the caller of a Gate may send into your Machine. Give the result to jr2Setup({ events }), and write its name as an on key on the states that take it. An Agent sees each event it may send as one tool on its Menu.
It gives back a frozen EventDef and registers nothing. Each Machine whose jr2Setup lists the event takes it. A Machine that does not list it does not take it.
Give an event only the params that the Machine reads. When a pick enters a state that invokes an Effect, createMachine refuses each param of the pick that nothing reads: the input of the Effect, an assign, or the fill of fromPick. The compiler does not find this error. jr2 check and jr2 up find it when they load the module. Thus when you copy a finish event with a summary and nothing uses the summary, drop summary from the input, or store it with assign.
It refuses:
- a name with a character other than a letter, a digit,
_or-:defineEvent: invalid name "<name>" — must match /^[a-zA-Z0-9_-]+$/ (it becomes an MCP tool name and an xstate event type) - an
inputwith asenderfield:defineEvent: "<name>" declares `sender` in its input — the Orchestrator writes that field on every delivered event (who sent it); name the payload field something else - an
outputfield:defineEvent: "<name>" declares an `output`, which is retired — every pick is answered when the work it started is done, and the answer is the Machine's, not the def's. Withsemantics: "deferred", the text saysdeclares `deferred`in place ofdeclares an `output`.
Parameters
def: The event: itsname, itsinputschema, and optionally itsdescription,semanticsandaudience.name:NameThe event's name: the
onkey that takes it, and the name of its tool on the Agent's Menu. Letters, digits,_and-only.description(optional):stringWhat the event means, and when to send it. An Agent's model reads it as the tool's description. Make it true at every state that takes the event.
input:InputThe schema of the payload: a flat
z.object. Usez.object({})for an event with no payload. Do not name a fieldsender: jr2 writes that field.semantics(optional):EventSemanticsHow the sender gets its answer. Default:
"ack", the only valuecreateMachineaccepts.audience(optional):EventAudienceWho may send the event:
"agent","external"or"any". Default: unset, and the state of eachonkey decides (seeEventAudience).
Returns: The event, as plain data to list in jr2Setup({ events }).
Example
import { z } from "zod";
import { agent, defineEvent, fail, jr2Setup } from "@jr2/orchestrator";
const done = defineEvent({
name: "done",
description: "Call this when the summary is written.",
input: z.object({ summary: z.string() }),
});
export const machine = jr2Setup({
events: [done],
actors: {
writer: agent({
model: "anthropic/claude-haiku-5-5",
instructions: "You write short summaries.",
workspace: "none",
}),
fail: fail(),
},
}).createMachine({
id: "summary",
on: { "agent.fault": ".failed" },
initial: "writing",
states: {
writing: {
invoke: { src: "writer", input: { prompt: "Summarize the release notes in one line." } },
on: { done: "finished" },
},
finished: { type: "final" },
failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
},
});See also