---
title: sentBy
description: "A guard that is true for an event that one party sent, and false for an event that another party sent: `guard: sentBy(\"coder\")`."
---

# `sentBy`

Function, in `@jr2/orchestrator/src/party.ts`. It is an export of `@jr2/orchestrator`, on the [Authoring surface](../authoring-surface.md) page, in Machine and events.

```ts
function sentBy<const Id extends string>(id: Id): { type: typeof SENT_BY; params: { id: Id } }
```

A guard that is true for an event that one party sent, and false for an event that another party
sent: `guard: sentBy("coder")`. Use it where two parties may send the same event to one state,
and the transition must run for one of them only. It is also true for an event that the Machine
sends itself, which has no sender.

It can only make a transition decline the events of other parties. It never lets a party send
an event that the party may not send at that state: the position of the `on` key decides that.
When the guard is false, xstate tries the next transition for the event, as for any guard. Use
it alone, or inside `and([…])`.

`createMachine` refuses an id that is not a party of the Machine: ``machine "<id>":
sentBy("<party>") on "<event>" at "<state>" names no party of this Machine (Agent slots:
<slots>; Gate invoke ids: <ids>)``

**Parameters**

- `id`: The party: the slot key of an Agent of this Machine, or the invoke `id` of one of its
  Gates.

**Returns**: A named guard object, for a transition's `guard`.

**Example**

```ts
import { z } from "zod";
import { agent, defineEvent, fail, jr2Setup, sentBy } from "@jr2/orchestrator";

const done = defineEvent({
  name: "done",
  description: "Call this when the draft is ready for review.",
  input: z.object({}),
});

export const machine = jr2Setup({
  events: [done],
  actors: {
    writer: agent({
      model: "anthropic/claude-haiku-5-5",
      instructions: "You write release notes.",
      workspace: "none",
    }),
    fail: fail(),
  },
}).createMachine({
  id: "notes",
  on: { "agent.fault": ".failed" },
  initial: "drafting",
  states: {
    drafting: {
      invoke: [
        { src: "writer", input: { prompt: "Draft the release notes." } },
        { src: "gate", id: "editor" },
      ],
      on: {
        // The writer's `done` goes to review; the editor's `done` skips it.
        done: [{ guard: sentBy("writer"), target: "review" }, { target: "published" }],
      },
    },
    review: { invoke: { src: "gate" }, on: { done: "published" } },
    published: { type: "final" },
    failed: { invoke: { src: "fail", input: { reason: "the Agent's Turn could not go on" } } },
  },
});
```

**See also**

- [The Menu](../../concepts/the-menu.md)
- [Gates](../../concepts/gates.md)
- [ADR-0015: Workflows are authored through `jr2Setup`; vocabulary and agent menus derive from the machine](../decisions/0015-authoring-surface-absorbs-the-mechanism.md)
