Skip to main content
Glama

Initiate Handoff

initiate_handoff
DestructiveIdempotent

Begin a handoff from the agent to either a human operator (SMS/email via lead_routing_json) or another agent (signed continuation URL). In human mode the notification body is composed by the server from the contact and reason fields — callers supply those fields, not the message text. Idempotent: re-using the same idempotency_key returns the original handoff.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
modeYesHandoff mode: human (SMS/email) or agent (continuation URL)
slugYesBusiness slug identifier
reasonNoWhy the user wants to reach a human
messageNoDeprecated alias for `reason`. The notification body is composed by the server from the fields above; this value is delivered as the reason line, not as the message itself. Supplying both is an error.
purposeNoPurpose description for agent-mode continuation
urgencyNoHow time-sensitive (default: normal)
agent_idNoOptional agent identifier
contact_nameNoEnd-user's name
contact_emailNoEnd-user's email
contact_phoneNoEnd-user's phone
reservation_idNoOptional link to a prior reservation
idempotency_keyYesUnique key for idempotent handoff

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
modeYesThe handoff's mode, and which of the fields below are present. Normally the mode you asked for — but an idempotent replay returns the STORED handoff's mode, which differs when an idempotency_key is reused with a different mode than the call that created it.
reasonNohuman mode, not delivered: 'form_routing_configured', 'no_recipient_configured', 'sms_consent_missing', a shape-mismatch skip, a spend-cap denial, or a provider failure code
statusNohuman mode replay while the original send is still in flight: 'pending'
channelNohuman mode, skipped before sending: the channel that would have been used ('sms' or 'email'), or 'form' when the business only takes leads through a web form
form_urlNohuman mode, channel 'form': the business's own contact form for the user to complete
deliveredNohuman mode: present only as false, when nothing was sent — see reason
ticket_idNohuman mode, delivered: the provider's message id, or the handoff_id when the provider issues none
expires_atNoagent mode: Unix seconds when continuation_url stops working (one hour)
handoff_idYes
delivered_viaNohuman mode: 'sms' or 'email' — the channel the notification went to
handshake_tokenNoagent mode: the bare token carried inside continuation_url
continuation_urlNoagent mode: signed URL the next agent redeems exactly once at /a2a/continue
idempotent_replayNoPresent and true when this idempotency_key already had a handoff; nothing was re-sent and no token was re-minted
continuation_expiredNoagent mode replay: true when the stored continuation has already expired; it is never re-minted — start a new handoff

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "http://json-schema.org/draft-07/schema#",
      +  "additionalProperties": false,
      +  "properties": {
      +    "channel": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "human mode, skipped before sending: the channel that would have been used ('sms' or 'email'), or 'form' when the business only takes leads through a web form"
      +    },
      +    "continuation_expired": {
      +      "description": "agent mode replay: true when the stored continuation has already expired; it is never re-minted — start a new handoff",
      +      "type": "boolean"
      +    },
      +    "continuation_url": {
      +      "description": "agent mode: signed URL the next agent redeems exactly once at /a2a/continue",
      +      "type": "string"
      +    },
      +    "delivered": {
      +      "description": "human mode: present only as false, when nothing was sent — see reason",
      +      "type": "boolean"
      +    },
      +    "delivered_via": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "human mode: 'sms' or 'email' — the channel the notification went to"
      +    },
      +    "expires_at": {
      +      "description": "agent mode: Unix seconds when continuation_url stops working (one hour)",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "form_url": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "human mode, channel 'form': the business's own contact form for the user to complete"
      +    },
      +    "handoff_id": {
      +      "format": "uuid",
      +      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      +      "type": "string"
      +    },
      +    "handshake_token": {
      +      "description": "agent mode: the bare token carried inside continuation_url",
      +      "type": "string"
      +    },
      +    "idempotent_replay": {
      +      "description": "Present and true when this idempotency_key already had a handoff; nothing was re-sent and no token was re-minted",
      +      "type": "boolean"
      +    },
      +    "mode": {
      +      "description": "The handoff's mode, and which of the fields below are present. Normally the mode you asked for — but an idempotent replay returns the STORED handoff's mode, which differs when an idempotency_key is reused with a different mode than the call that created it.",
      +      "enum": [
      +        "human",
      +        "agent"
      +      ],
      +      "type": "string"
      +    },
      +    "reason": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "human mode, not delivered: 'form_routing_configured', 'no_recipient_configured', 'sms_consent_missing', a shape-mismatch skip, a spend-cap denial, or a provider failure code"
      +    },
      +    "status": {
      +      "description": "human mode replay while the original send is still in flight: 'pending'",
      +      "type": "string"
      +    },
      +    "ticket_id": {
      +      "anyOf": [
      +        {
      +          "type": "string"
      +        },
      +        {
      +          "type": "null"
      +        }
      +      ],
      +      "description": "human mode, delivered: the provider's message id, or the handoff_id when the provider issues none"
      +    }
      +  },
      +  "required": [
      +    "mode",
      +    "handoff_id"
      +  ],
      +  "type": "object"
      +}
  2. Changed7 schema fields changed
    • addedInput schema / properties / contact_email
      Added value: +{
      +  "description": "End-user's email",
      +  "format": "email",
      +  "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
      +  "type": "string"
      +}
    • addedInput schema / properties / contact_name
      Added value: +{
      +  "description": "End-user's name",
      +  "maxLength": 120,
      +  "type": "string"
      +}
    • addedInput schema / properties / contact_phone
      Added value: +{
      +  "description": "End-user's phone",
      +  "maxLength": 40,
      +  "type": "string"
      +}
    • changedInput schema / properties / message / description
      Previous value: -"Message body for human-mode notification"New value: +"Deprecated alias for `reason`. The notification body is composed by the server from the fields above; this value is delivered as the reason line, not as the message itself. Supplying both is an error."
    • addedInput schema / properties / message / maxLength
      Added value: +800
    • addedInput schema / properties / reason
      Added value: +{
      +  "description": "Why the user wants to reach a human",
      +  "maxLength": 800,
      +  "type": "string"
      +}
    • addedInput schema / properties / urgency
      Added value: +{
      +  "description": "How time-sensitive (default: normal)",
      +  "enum": [
      +    "low",
      +    "normal",
      +    "high",
      +    "emergency"
      +  ],
      +  "type": "string"
      +}
  3. Changed10 schema fields changed
    • removedInput schema / additionalProperties
      Removed value: -false
    • addedInput schema / properties / agent_id
      Added value: +{
      +  "description": "Optional agent identifier",
      +  "type": "string"
      +}
    • addedInput schema / properties / idempotency_key
      Added value: +{
      +  "description": "Unique key for idempotent handoff",
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / message
      Added value: +{
      +  "description": "Message body for human-mode notification",
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / mode / description
      Added value: +"Handoff mode: human (SMS/email) or agent (continuation URL)"
    • removedInput schema / properties / payload
      Removed value: -{
      -  "additionalProperties": {},
      -  "type": "object"
      -}
    • addedInput schema / properties / purpose
      Added value: +{
      +  "description": "Purpose description for agent-mode continuation",
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / reservation_id / description
      Added value: +"Optional link to a prior reservation"
    • addedInput schema / properties / slug / description
      Added value: +"Business slug identifier"
    • changedInput schema / required
      Previous value: -[
      -  "slug",
      -  "mode",
      -  "payload"
      -]New value: +[
      +  "slug",
      +  "mode",
      +  "idempotency_key"
      +]
  4. Changed10 schema fields changed
    • addedInput schema / additionalProperties
      Added value: +false
    • removedInput schema / properties / agent_id
      Removed value: -{
      -  "description": "Optional agent identifier",
      -  "type": "string"
      -}
    • removedInput schema / properties / idempotency_key
      Removed value: -{
      -  "description": "Unique key for idempotent handoff",
      -  "minLength": 1,
      -  "type": "string"
      -}
    • removedInput schema / properties / message
      Removed value: -{
      -  "description": "Message body for human-mode notification",
      -  "minLength": 1,
      -  "type": "string"
      -}
    • removedInput schema / properties / mode / description
      Removed value: -"Handoff mode: human (SMS/email) or agent (continuation URL)"
    • addedInput schema / properties / payload
      Added value: +{
      +  "additionalProperties": {},
      +  "type": "object"
      +}
    • removedInput schema / properties / purpose
      Removed value: -{
      -  "description": "Purpose description for agent-mode continuation",
      -  "minLength": 1,
      -  "type": "string"
      -}
    • removedInput schema / properties / reservation_id / description
      Removed value: -"Optional link to a prior reservation"
    • removedInput schema / properties / slug / description
      Removed value: -"Business slug identifier"
    • changedInput schema / required
      Previous value: -[
      -  "slug",
      -  "mode",
      -  "idempotency_key"
      -]New value: +[
      +  "slug",
      +  "mode",
      +  "payload"
      +]
  5. Changed10 schema fields changed
    • removedInput schema / additionalProperties
      Removed value: -false
    • addedInput schema / properties / agent_id
      Added value: +{
      +  "description": "Optional agent identifier",
      +  "type": "string"
      +}
    • addedInput schema / properties / idempotency_key
      Added value: +{
      +  "description": "Unique key for idempotent handoff",
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / message
      Added value: +{
      +  "description": "Message body for human-mode notification",
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / mode / description
      Added value: +"Handoff mode: human (SMS/email) or agent (continuation URL)"
    • removedInput schema / properties / payload
      Removed value: -{
      -  "additionalProperties": {},
      -  "type": "object"
      -}
    • addedInput schema / properties / purpose
      Added value: +{
      +  "description": "Purpose description for agent-mode continuation",
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / reservation_id / description
      Added value: +"Optional link to a prior reservation"
    • addedInput schema / properties / slug / description
      Added value: +"Business slug identifier"
    • changedInput schema / required
      Previous value: -[
      -  "slug",
      -  "mode",
      -  "payload"
      -]New value: +[
      +  "slug",
      +  "mode",
      +  "idempotency_key"
      +]
  6. First observed

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds useful nuance beyond the annotations, especially the idempotent key behavior and the server-side composition of notification bodies. However, the annotations mark destructiveHint true and the description does not disclose any destructive or irreversible effects, leaving part of the behavior unexplained.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the core purpose, then adds only the two most decision-relevant clarifications: mode behavior and idempotency. No sentence is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema, annotations, and 100% schema description coverage, the description fills the remaining gaps around mode semantics and idempotent behavior. It does not detail destructive aspects, but for the tool's complexity it is sufficiently complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already covers all 12 parameters, but the description adds significant meaning: callers supply contact and reason fields in human mode, message is a deprecated alias, and idempotency prevents duplicates. This helps the agent choose and populate parameters correctly beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool begins a handoff and gives the two concrete modes (human operator vs. another agent), making the verb, resource, and scope unambiguous. It also distinguishes its function from the sibling tools without requiring schema inspection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explains when this tool is relevant, including the two distinct handoff targets and how human notifications are composed server-side. It does not explicitly name alternative tools or spell out exclusion caveats, but the context is clear enough for a selecting agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.