Signals

Understand a person's Stop request and ask them to authenticate or choose an option.

Signals are optional metadata attached to an agent activity. They clarify how the recipient should handle it: a person can ask the app to stop, and the app can ask Pulse to present an account connection or a choice. The activity still carries the message itself; the signal explains the intended action.

The signal travels with the activity. A human prompt can carry stop. An app can attach auth or select to an elicitation, with details in signal_metadata. The session, activity and webhook still work as described in developing the agent interaction.

Human-to-agent signals

These signals arrive on prompt activities. Check the signal field instead of inferring intent from the message text.

stop

When a person presses Stop in the session panel, Pulse moves the session to stopping and sends prompted with agent_activity.signal set to "stop". The same signal is sent when delegation is removed.

A stop signal arrives on a prompt when a person presses Stop or delegation changes. It asks the app to stop work immediately; the text Stop without the signal is not enough to identify this request.

The webhook has this shape:

Check agent_activity.signal === "stop" — do not guess from the text. Then:

  1. Stop everything: cancel running tool calls, drop queued follow-ups, change nothing more in Pulse or elsewhere.
  2. Post one final response (what was done and what state things are in) or error.
{ "content": { "type": "response", "body": "Stopped. I had read the issue; nothing was changed." } }

Your final activity ends the session as complete with end_reason: stopped. If none arrives within 60 seconds, Pulse ends it anyway. After that, writes answer 409 SESSION_ENDED.

Pulse sends the same stop when the issue is undelegated or delegated to another agent, with end_reason: undelegated on the session. Handle it the same way. Uninstall, team removal and issue deletion end the session at once without a stop, because your app no longer has access to answer; see When Pulse ends a session.

Agent-to-human signals

An elicitation pauses the session in awaitingInput. Use a signal when Pulse can offer a more specific action than a free-form reply.

auth

Ask a person to connect an account your app needs, such as their GitHub account. Post an elicitation with signal: "auth":

{
  "content": { "type": "elicitation", "body": "I need access to your GitHub account to open the pull request." },
  "signal": "auth",
  "signal_metadata": {
    "url": "https://scout.acme.example/connect/github?session=sess_01J9Z3K8T5N2",
    "user_id": "68d91d3629c051fe043158f9",
    "provider_name": "GitHub"
  }
}
signal_metadata fieldRequiredMeaning
urlYesYour https:// page where the person connects. Opens in a new tab.
user_idNoOnly this Pulse user sees the button
provider_nameNoShown on the button as "Connect ‹provider_name›"

The session moves to awaitingInput. When your connect page finishes, resume by posting a thought; the button disappears once any later activity arrives.

select

Offer options instead of an open question. Post an elicitation with signal: "select" and 1–10 options:

{
  "content": { "type": "elicitation", "body": "Which environment should I deploy to?" },
  "signal": "select",
  "signal_metadata": {
    "options": [
      { "value": "staging", "label": "Staging" },
      { "value": "production", "label": "Production" }
    ]
  }
}

Each option has a value and an optional label shown on the button (the value when absent). When the person picks one, you receive a normal prompted event whose agent_activity.content.body is that option's value:

{ "agent_activity": { "content": { "type": "prompt", "body": "staging" } } }

People may ignore the buttons and type their own answer, so the body can be any text ("staging, but only after 6 pm"). Interpret it, for example with a model, rather than matching it exactly.

Last updated on