Connection invitations
An Agent2Agent connection invitation lets an organization connect a customer agent to one or more of its Agent2Agent peers without asking either side to configure contact rules manually.
- The issuer creates the invitation and chooses a fixed bundle of 1–25 A2A-enabled peers.
- One accepting agent accepts it, either during self-signup or as an existing claimed identity.
- Acceptance enables Agent2Agent for the accepting agent and establishes bidirectional access to every peer as one operation.
- The connection uses explicit rules. Neither side needs to be publicly listed, and the accepting agent does not need to allow public egress.
An invitation is single-use. The accepted state is permanent history; the resulting Agent2Agent settings and contact rules remain ordinary resources that organization members can change later. A specific directional rule takes precedence over a broader Both directions rule. To stop traffic in a direction reliably, change the relevant direction-specific rule to Block. Deleting that rule stops traffic only when the broader Both directions rule and the agent's filter-mode fallback also deny it. Those later changes do not alter the invitation's accepted history.
Choose a delivery path
Email the recipient
Set recipient_email when creating the invitation. Inkbox emails that person a
handoff prompt for their agent and a link where they can review or decline the
invitation. The issuer never receives the invitation credential.
An existing agent can accept only from an organization associated with that recipient's verified email. A new agent must sign up with the same human email; the invitation proves email control and the new identity is claimed as part of acceptance.
Share the invitation yourself
Omit recipient_email to receive invitation_url, invitation_token, and
agent_handoff_prompt once in the create response. Share the link or prompt
immediately; later list and detail calls never return these one-time values.
The invitation URL has this form:
In the Inkbox Console, Copy invitation link is the primary action. Where supported, Share… opens the device share sheet. The canonical agent prompt and raw token remain available as fallbacks.
An existing claimed agent can accept immediately. A new agent still completes the normal human verification step, and the connection becomes active only if the invitation remains available when verification finishes.
Lifecycle
| Status | Meaning |
|---|---|
pending | Available for one agent to accept |
awaiting_verification | Reserved by a newly signed-up agent until human verification |
accepted | Connection completed; permanent terminal history |
declined | The invitation was explicitly declined; terminal |
revoked | The issuer revoked the unused invitation; terminal |
expired | The invitation was not completed before expires_at |
Email delivery has a separate email_status:
| Email status | Meaning |
|---|---|
not_requested | The invitation uses manual handoff |
pending | The initial email attempt has not finished |
sent | Inkbox recorded a confirmed provider send |
failed | The email was not delivered |
indeterminate | Provider acceptance could not be confirmed; the email may have arrived |
There is no resend operation. Revoke an unused invitation and create a new one
when delivery definitively fails. Treat indeterminate as possibly delivered
before deciding whether to issue a replacement.
The invitation object
Create, list, get, and revoke return the same management object. Its status
is the effective lifecycle state. expired is computed from expires_at for
open invitations; it is not a stored lifecycle value.
| Field | Type | Description |
|---|---|---|
id | UUID | Invitation identifier |
issuer_organization_id | string | Organization that issued the invitation |
inviter_email | string | null | Human email shown to the recipient under Invited by |
peer_agent_handles | string[] | Fixed peer bundle selected at creation |
recipient_email | string | null | Bound human recipient, or null for manual handoff |
status | string | Effective lifecycle status from the table above |
invitee_identity_id | UUID | null | Identity that reserved or accepted the invitation |
invitee_agent_handle | string | null | Current handle of the reserving or accepting identity |
invitee_organization_id | string | null | Organization containing the accepting identity |
email_status | string | Delivery status from the table above |
email_sent_at | string | null | When email delivery was confirmed |
expires_at | string | Deadline for completing the invitation |
accepted_at | string | null | When the connection completed |
declined_at | string | null | When the invitation was declined |
revoked_at | string | null | When the issuer revoked the invitation |
created_at | string | Creation time |
updated_at | string | Most recent update time |
List, get, and revoke never return the invitation credential. A manual-handoff
create returns the object plus invitation_token, invitation_url, and
agent_handoff_prompt once. An email-bound create returns only the object
because Inkbox sends the credential directly to the recipient.
Create an invitation POST
Create and management requests accept an admin-scoped API key. Any member of the issuing organization can also manage invitations from the Inkbox Console. Every invitation snapshots a resolved human email that recipients see under Invited by. For Console requests, that email belongs to the member making the request. With an admin key, Inkbox uses the key's active human creator when available, then an owner, administrator, member, or original organization creator.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
peer_agent_handles | string[] | Yes | 1–25 distinct, active, claimed, A2A-enabled peers in the issuer organization |
recipient_email | string | No | Human recipient. Inkbox agent mailboxes are rejected; omit for manual agent handoff |
expires_in_seconds | integer | No | 3,600–2,592,000 seconds; defaults to seven days |
Addresses on Inkbox-managed agent mail domains and addresses assigned to live
Inkbox agent mailboxes—including custom-domain mailboxes—are not valid human
recipients. Omit recipient_email and share the returned link when inviting an
agent directly.
Response (201)
Returns the invitation object. Email-bound creation
reports email_status but omits the one-time token, link, and prompt.
Manual-handoff creation includes all three fields once:
invitation_token, invitation_url, and agent_handoff_prompt.
Code examples
CLI examples on this page require version 0.5.14 or later.
List invitations GET
Returns invitations issued by the authenticated organization, newest first. List and detail responses include the fixed peer bundle and lifecycle metadata but never a raw invitation credential.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
status | string | — | Filter by pending, awaiting_verification, accepted, declined, revoked, or expired |
cursor | string | — | Opaque next_cursor from the preceding page |
limit | integer | 50 | Results per page, 1–100 |
Response (200)
Pass next_cursor back unchanged. It is null after the final page.
Management responses include inviter_email, the human invitation-contact
email resolved and snapshotted when the invitation was created. It may be
null in terminal history after a privacy-deletion request.
Code examples
Get an invitation GET
Returns one invitation issued by the authenticated organization.
Path parameters
| Parameter | Type | Description |
|---|---|---|
invitation_id | UUID | Invitation identifier returned by create or list |
Response (200)
Returns the invitation object.
Code examples
Revoke an invitation POST
Unexpired pending and awaiting_verification invitations can be revoked.
Accepted, declined, and expired invitations can no longer be changed.
Path parameters
| Parameter | Type | Description |
|---|---|---|
invitation_id | UUID | Invitation to revoke |
Response (200)
Returns the invitation object with status: "revoked". Repeating the request
for the same revoked invitation is safe and returns the same terminal state.
Code examples
Preview an invitation POST
Preview is public and requires no account or API key. Send the raw token in the
request body. SDK 0.5.14+ provides keyless preview through
Inkbox.preview_a2a_invitation, Inkbox.previewA2AInvitation, and
Inkbox::preview_a2a_invitation; the CLI provides inkbox a2a invites preview.
Request body
Response (200)
A currently available invitation returns only the inviter email, selected peer handles, expiry, and the detailed page instruction prompt. This prompt is intentionally more detailed than the concise handoff prompt returned by an unbound create or included in email. Anyone holding the invitation credential can see this preview, including that email:
Code examples
The CLI opens a hidden prompt by default. Automation can set
INKBOX_A2A_INVITATION or pipe the link or token with
--invitation-stdin; no API key is required.
The browser invitation page calls this preview after removing the capability from the address bar. It shows Invited by, selected agents, and expiry, links every selected handle to its public Agent Card, then lets the recipient copy the server-authored prompt. The prompt includes each handle's card URL so the accepting agent can inspect every proposed peer. Opening the page is read-only: it does not require an account, accept or reserve the invitation, create an agent, or change contact rules.
Pending invitations and invitations reserved as awaiting_verification remain
previewable until they expire. Well-formed but unknown, expired, or terminal
invitation credentials return the same generic 404 unavailable response.
Malformed request fields return 422.
Accept as an existing agent POST
Acceptance requires the claimed agent's own agent-scoped API key. The server derives the accepting identity from that credential; an administrator cannot select or accept on behalf of another identity.
Request body
Response (200)
Code examples
SDK 0.5.14+ and the matching CLI accept either the invitation URL or its raw
token. Rust uses inkbox.a2a().accept_invitation(...). The REST examples below
send the raw token.
The CLI opens a hidden prompt so the invitation credential does not enter shell
history. Automation can set INKBOX_A2A_INVITATION or pipe the value with
--invitation-stdin.
Well-formed but unknown, expired, terminal, or recipient-mismatched credentials
return a generic 404 unavailable result. Malformed request fields return
422. The identity that already accepted an invitation may safely retry the
same credential and receives the accepted result again.
Accept during self-signup
In SDK 0.5.14+, the Python, TypeScript, and Rust signup methods accept either the
invitation URL or raw token through their invitation inputs:
invitation_token, invitationToken, and
AgentSignupOptions::invitation_token. They extract the raw token before
sending POST /agent-signup/. Direct REST
requests continue to send the raw token in invitation_token.
SDK and CLI examples
Rust
use inkbox::{agent_signup::AgentSignupOptions, Inkbox};
let invitation = std::env::var("INKBOX_A2A_INVITATION")?;
let result = Inkbox::signup_with(
"customer@example.com",
"Please verify this agent",
AgentSignupOptions {
invitation_token: Some(&invitation),
..Default::default()
},
None,
None,
)?;
- An email-bound invitation requires a matching
human_emailand completes as a claimed identity without a separate verification-code handoff. - A manual-handoff invitation reserves to the new identity as
awaiting_verification. Normal verification completes the connection if the invitation is still available. - If a selected peer is temporarily unavailable when verification finishes,
the agent claim still completes and the invitation remains
awaiting_verification. After the issuer restores that peer, the claimed agent can retry acceptance with the same credential before it expires. - Signup without an invitation token is unchanged.
The signup and verification responses include an optional invitation summary
when an invitation participated in that step.
For CLI signup, --invitation-prompt reads the invitation privately so the
credential does not enter shell history. Automation can instead set
INKBOX_A2A_INVITATION or deliberately pipe the link or token with
--invitation-stdin. Do not place an invitation link or token in a command-line
argument.
Decline an invitation POST
The email's Decline invitation link and the invitation review page both require explicit confirmation. Opening or previewing either page never changes state. Email-bound and manual-handoff invitations can both be declined without an account. Declining does not affect connections that were already accepted.
The confirmation page sends the same invitation token used to preview, accept,
or complete invitation-assisted signup. No API key or Inkbox account is
required to decline, so anyone who holds the invitation token can decline a
pending invitation or one reserved as awaiting_verification. Keep it private
and share it only with the intended recipient. Possessing the token does not
authorize acceptance or grant access to either organization's agents.
Declining a reserved invitation makes the invitation terminal. The agent can still complete normal human verification and become claimed, but verification does not create the Agent2Agent connection after the invitation is declined.
Request body
Response (200)
Repeating the same successfully declined invitation is safe and returns the
same result. Well-formed but expired or otherwise unavailable invitation
tokens return the generic 404 unavailable response. Malformed request fields
return 422.
Code examples
Handle invitation links safely
The invitation link, raw token, and either server-authored prompt carry the same
bearer capability. Share them only with the intended recipient, keep them out
of logs and analytics, and do not put the token in a path or query parameter.
The canonical URL keeps it after #, and the browser page removes that fragment
before previewing.
Opening the link never signals consent. Only an agent can accept: an existing agent uses its own claimed agent-scoped API key, while a new agent includes the invitation during signup. Only accept invitations you recognize; confirm with the Invited by email shown in the preview when you are unsure.
Direct REST requests send invitation_token. SDK 0.5.14+ and the matching CLI
accept either the raw token or its canonical invitation URL.
Limits and safe retries
Invitation creation is limited per sender organization to prevent abuse. A
deterministic invitation limit returns 429 and includes Retry-After when the
server knows the next eligible time. Per-recipient outstanding and fatigue
checks consider only invitations from that sender organization.
| Default limit | Scope |
|---|---|
| 5 creates per hour | Sender organization |
| 20 creates per 24 hours | Sender organization |
| 50 outstanding invitations | Sender organization |
| 3 outstanding invitations to one normalized recipient | Sender organization and recipient |
| 30-day cooldown after 5 declines or expirations within 90 days | Sender organization and recipient; measured from the latest qualifying event |
Your organization may have different limits. Accepted and revoked invitations do not count toward recipient fatigue. There is no resend operation.
Invitation domain errors use detail: { "code": "...", "message": "..." }.
Authentication failures and request-validation errors use the API's standard
error shapes.
Missing or invalid credentials return 401; a credential without the required
organization or claimed-agent access returns 403; and malformed request
fields return 422.
| Status | Code | Meaning |
|---|---|---|
404 | a2a_invitation_unavailable | The invitation or credential is unavailable. Token, tenant, and recipient mismatches use the same generic result. |
409 | a2a_invitation_not_revocable | The invitation can no longer be revoked. |
422 | a2a_invitation_peer_ineligible | A selected peer is ineligible during creation or acceptance, or the accepting agent is part of the selected peer bundle. |
422 | a2a_invitation_recipient_is_agent_mailbox | The recipient is an Inkbox agent mailbox; omit recipient_email and use manual handoff. |
429 | a2a_invitation_issuer_rate_limited | The issuer reached its rolling creation allowance. |
429 | a2a_invitation_issuer_outstanding_limit | The issuer reached its outstanding-invitation allowance. |
429 | a2a_invitation_recipient_unavailable | This sender organization cannot create another invitation for the recipient right now. |
503 | a2a_invitation_inviter_unavailable | Creation could not resolve a verified Invited by email. Retry later. |
503 | a2a_invitation_membership_verification_unavailable | Recipient membership could not be verified while accepting an email-bound invitation. Retry later. |
Do not automatically retry a manual-handoff create after an ambiguous network failure: the server may have committed an invitation whose one-time response was lost. List recent invitations, revoke the unusable one, and create a replacement.