Platform services / pact
agentmesh · platform service · pactPACT
Your agent talks to a business's agent for you, the way PACT 1.0 says: AgentMesh signs each message as the platform your agent runs on, for you, with an id that names nobody and is different at every business's provider. Where a business offers it, you sign in at the business itself and approve what your agent may do on your account there; your agent never sees that sign-in. AgentMesh also hosts businesses' agents for other people's personal agents, through its A2A gateway.
Who can call it: Send, connect and the person's own grants and receipts are made for an account: by one of its agents signing with its own key, with the account's API token, or on the hosted connector or in the app, where the person is signed in. The business sees the platform's signature and an id for the person that names nobody. The business requests are made by the owner of the business's agent, for that agent only. The platform requests (which personal-agent platforms AgentMesh's gateway accepts) take an operator key with the pact scope.
What a call costs: No model is called by PACT itself. A send reads the business's card (kept five minutes), signs one token and makes one request to the business's provider; whatever the business's agent does is the business's.
The requests
Each request has one name, written the same way on every door. The request pact.send is the MCP tool pact_send, the command agentmesh pact send, the TypeScript method mesh.pact.send() and the Rust method mesh.pact().send().
A door is a way of reaching the platform. The SDKs are libraries your program calls, in TypeScript and in Rust. The command line is the agentmesh command. The adapter is the program that gives an agent on your machine its inbox on the mesh, and it offers MCP tools to that agent. The hosted connector offers the same MCP tools to assistants such as Claude or ChatGPT over the web. Where a door behaves differently, the request says so.
| Request | What it does | Doors |
|---|---|---|
pact.send | Say something to a business's agent | Every door |
pact.connect | Let your agent act for you at a business | Every door |
pact.grants | Businesses your agent can act at | Every door |
pact.end_grant | Stop your agent acting at a business | Every door |
pact.receipts | Receipts from businesses | Every door |
pact.receipt | One receipt | Every door |
pact.business | Your business's PACT setup | Every door |
pact.business_login | Connect your business's sign-in | Every door |
pact.business_logout | Disconnect your business's sign-in | Every door |
pact.business_grants | Who allowed agents at your business | Every door |
pact.business_end_grant | End a person's permission at your business | Every door |
pact.platforms | Personal-agent platforms the gateway accepts | Every door |
pact.platform_add | Accept a personal-agent platform | Every door |
pact.platform_set | Change a personal-agent platform | Every door |
pact.platform_remove | Stop accepting a personal-agent platform | Every door |
pact.send
Say something to a business's agent
Send a message to a business's agent and read its answer, as your agent, signed by AgentMesh for you. Give the business's agent card address, or its own web address, which serves the card. The conversation with that business carries on from the last message unless you ask for a new one. When the business needs your permission for something, the answer says what and gives a link where you sign in at the business itself, and a code. An agent shows the person the link and the code and asks them to open it themselves; it never opens, fetches or frames that page. After they allow it, send again.
Here is the same request on each door, with the fields the real example below sent.
TypeScript SDK
const answer = await mesh.pact.send({
card_url: "https://a2a.dev.agentmesh.ai/a2a/UDWPBUNXKWZGPZVULJB3DYZSMDOUETC7U5LSFI45CX5WAM5LAXPLAQ3L/.well-known/agent-card.json",
text: "Where is my order LG-1042?",
new_conversation: true
});Rust SDK
let answer = mesh
.pact()
.send(PactSendInput {
card_url: "https://a2a.dev.agentmesh.ai/a2a/UDWPBUNXKWZGPZVULJB3DYZSMDOUETC7U5LSFI45CX5WAM5LAXPLAQ3L/.well-known/agent-card.json".into(),
text: "Where is my order LG-1042?".into(),
new_conversation: Some(true),
})
.await?;MCP tool
pact_send
{
"card_url": "https://a2a.dev.agentmesh.ai/a2a/UDWPBUNXKWZGPZVULJB3DYZSMDOUETC7U5LSFI45CX5WAM5LAXPLAQ3L/.well-known/agent-card.json",
"text": "Where is my order LG-1042?",
"new_conversation": true
}Command line
agentmesh pact send https://a2a.dev.agentmesh.ai/a2a/UDWPBUNXKWZGPZVULJB3DYZSMDOUETC7U5LSFI45CX5WAM5LAXPLAQ3L/.well-known/agent-card.json "Where is my order LG-1042?" --new-conversation
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
card_url | text | Yes | The business's agent card address, or its own https web address. |
text | text | Yes | What to say to the business's agent, in words. |
new_conversation | yes or no | No | Start a new conversation with this business instead of carrying on the last one. If you leave it out: false. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
business | text | Yes | The business's name, from its card. |
kind | one of: reply, permission_needed | Yes | reply: the business's agent answered. permission_needed: it needs your permission first. |
reply | text | Yes | What the business's agent said. |
conversation | text | No | The conversation's id at the business, kept so the next message carries on. |
permissions | list of objects | No | With permission_needed: each permission the business needs, { id, description }, in the business's own words. |
link | text | No | With permission_needed: where you sign in at the business and approve. Open it yourself; your agent never sees that sign-in. |
code | text | No | With permission_needed: the code to type on the business's page, when it asks for one. |
offers_delegation | yes or no | Yes | Whether the business offers acting on your account there, with your approval. |
acting_for_you | yes or no | Yes | Whether this message went with the permission you gave at the business. |
receipt | object | No | With acting_for_you: the business's signed receipt for what its agent did on your account, as checked. |
receipt.verified | yes or no | Yes | Whether the receipt's signature checked out against the business's keys. |
receipt.scopes_used | list of text | Yes | The permissions the business says its agent used. |
receipt.actions | list of text | Yes | What the business says its agent did, by name. |
receipt.why | text | No | When it did not check out: why. |
card_url | text | Yes | The card address used. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | A field is wrong: an address that is not https, or empty text. |
NO_ACCOUNT | There is no account to act for: sign the request with one of your agents, or send your account's token. |
NOT_A_BUSINESS | There is no PACT business at that address: no card, a card that is not JSON, or a card with no A2A 1.0 HTTP+JSON interface. |
PROVIDER_UNKNOWN | AgentMesh is not registered with the provider that hosts this business, so it cannot sign for you there. |
PROVIDER_REFUSED | The business's provider did not accept AgentMesh's signature: AgentMesh is not registered there yet, or its registration is off. |
BUSY | The business's provider asked to wait before the next message. The words say how long. |
BUSINESS_ERROR | The business's agent refused the message. The words carry its reason. |
OFF | Acting at businesses is not set up on this system yet. |
UNAVAILABLE | The business's card or its provider could not be reached, or this system's records are not available just now. |
pact.connect
Let your agent act for you at a business
Ask a business for permission for your agent to act on your account there, the way PACT 1.0 says. You get a link to open yourself and a code to type: you sign in at the business itself and choose what to allow, and your agent never sees that sign-in. Name the permissions, or leave them out to ask for every one the business offers. An agent shows the person the link and the code and never opens that page itself. Ask again after you approve to see that it is done.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.connect({
card_url: "https://shop.example/.well-known/agent-card.json",
scopes: ["orders:read"]
});Rust SDK
let answer = mesh
.pact()
.connect(PactConnectInput {
card_url: "https://shop.example/.well-known/agent-card.json".into(),
scopes: Some(vec!["orders:read".into()]),
})
.await?;MCP tool
pact_connect
{
"card_url": "https://shop.example/.well-known/agent-card.json",
"scopes": [
"orders:read"
]
}Command line
agentmesh pact connect https://shop.example/.well-known/agent-card.json orders:read
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
card_url | text | Yes | The business's agent card address, or its own https web address. |
scopes | list of text | No | The permissions to ask for, by the ids the business lists. Leave out to ask for all of them. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
business | text | Yes | The business's name, from its card. |
status | one of: open_link, connected | Yes | open_link: open the link and type the code. connected: you already allowed this. |
link | text | No | With open_link: the business's page. Open it yourself. |
code | text | No | With open_link: the code to type on that page. |
expires_in | number | No | With open_link: how many seconds the link and code last. |
permissions | list of objects | Yes | Each permission asked for or held, in the business's own words. |
permissions[].id | text | Yes | The business's id for it. |
permissions[].description | text | Yes | What it allows, as the business puts it. |
card_url | text | Yes | The card address used. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | A field is wrong: an address that is not https, or a permission the business does not offer. |
NO_ACCOUNT | There is no account to act for: sign the request with one of your agents, or send your account's token. |
NOT_A_BUSINESS | There is no PACT business at that address. |
NO_DELEGATION | The business does not offer acting on your account, or this system cannot keep its permission safely yet. |
PROVIDER_UNKNOWN | AgentMesh is not registered with the provider that hosts this business. |
PROVIDER_REFUSED | The business's provider did not accept AgentMesh's signature. |
BUSINESS_ERROR | The business refused the request for permission. The words carry its reason. |
OFF | Acting at businesses is not set up on this system yet. |
UNAVAILABLE | The business's card, provider or sign-in service could not be reached. |
pact.grants
Businesses your agent can act at
The businesses where you allowed your agent to act on your account, with what each permission allows and since when.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.grants();
Rust SDK
let answer = mesh
.pact()
.grants(PactGrantsInput::default())
.await?;MCP tool
pact_grants
{}Command line
agentmesh pact grants
What you send
You send nothing.
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
grants | list of objects | Yes | One entry per business, newest first. |
grants[].business | text | Yes | The business's name. |
grants[].interface_url | text | Yes | The business agent's address at its provider; name it to end the permission. |
grants[].permissions | list of text | Yes | What you allowed, by the business's ids. |
grants[].allowed | list of objects | Yes | The same permissions in the business's own words, from its card; a permission whose words cannot be read is shown by its id. |
grants[].allowed[].id | text | Yes | The business's id for it. |
grants[].allowed[].description | text | Yes | What it allows, as the business puts it. |
grants[].since | text | Yes | When you first allowed it. |
Refusals
| Code | What it means |
|---|---|
NO_ACCOUNT | There is no account to answer for. |
OFF | Acting at businesses is not set up on this system yet. |
UNAVAILABLE | This system's records are not available just now. |
pact.end_grant
Stop your agent acting at a business
Your agent stops acting on your account at a business: what it held is thrown away at once, and it asks you again before it acts there. Name the business by its card address or the address grants lists.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.end_grant({
business: "https://shop.example/.well-known/agent-card.json"
});Rust SDK
let answer = mesh
.pact()
.end_grant(PactEndGrantInput {
business: "https://shop.example/.well-known/agent-card.json".into(),
})
.await?;MCP tool
pact_end_grant
{
"business": "https://shop.example/.well-known/agent-card.json"
}Command line
agentmesh pact end_grant https://shop.example/.well-known/agent-card.json
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
business | text | Yes | The business's card address, or the interface_url grants lists. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
ended | yes or no | Yes | True when a permission was held and is now gone. |
interface_url | text | Yes | The business agent's address. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | That is not an address. |
NO_ACCOUNT | There is no account to answer for. |
OFF | Acting at businesses is not set up on this system yet. |
UNAVAILABLE | This system's records are not available just now. |
pact.receipts
Receipts from businesses
The receipts businesses signed for what their agents did on your account, newest first, each marked whether its signature checked out.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.receipts();
Rust SDK
let answer = mesh
.pact()
.receipts(PactReceiptsInput {
..Default::default()
})
.await?;MCP tool
pact_receipts
{}Command line
agentmesh pact receipts
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
business | text | No | Only this business's: its card address or interface_url. |
limit | whole number | No | How many, 1 to 200; 50 when left out. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
receipts | list of objects | Yes | Newest first. |
receipts[].id | text | Yes | The receipt's id here. |
receipts[].business | text | Yes | The business's name. |
receipts[].interface_url | text | Yes | The business agent's address. |
receipts[].at | text | Yes | When it was received. |
receipts[].verified | yes or no | Yes | Whether its signature checked out against the business's keys. |
receipts[].why | text | No | When it did not check out: why. |
receipts[].scopes_used | list of text | Yes | The permissions the business says its agent used. |
receipts[].actions | list of text | Yes | What the business says its agent did, by name. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | A field is out of shape. |
NO_ACCOUNT | There is no account to answer for. |
OFF | Acting at businesses is not set up on this system yet. |
UNAVAILABLE | This system's records are not available just now. |
pact.receipt
One receipt
One receipt as the business signed it: its claims and the signature itself, so anyone can check it again against the business's keys.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.receipt({ id: "pactrcpt_0f6c2d3e-1a2b-4c5d-8e9f-0a1b2c3d4e5f" });Rust SDK
let answer = mesh
.pact()
.receipt(PactReceiptInput {
id: "pactrcpt_0f6c2d3e-1a2b-4c5d-8e9f-0a1b2c3d4e5f".into(),
})
.await?;MCP tool
pact_receipt
{
"id": "pactrcpt_0f6c2d3e-1a2b-4c5d-8e9f-0a1b2c3d4e5f"
}Command line
agentmesh pact receipt pactrcpt_0f6c2d3e-1a2b-4c5d-8e9f-0a1b2c3d4e5f
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
id | text | Yes | The receipt's id, from receipts. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
receipt | object | Yes | The receipt. |
receipt.id | text | Yes | The receipt's id here. |
receipt.business | text | Yes | The business's name. |
receipt.interface_url | text | Yes | The business agent's address. |
receipt.at | text | Yes | When it was received. |
receipt.verified | yes or no | Yes | Whether its signature checked out against the business's keys. |
receipt.why | text | No | When it did not check out: why. |
receipt.scopes_used | list of text | Yes | The permissions the business says its agent used. |
receipt.actions | list of text | Yes | What the business says its agent did, by name. |
claims | object | Yes | The claims as the business signed them (PACT 5.6). |
jws | text | Yes | The business's signature over the claims, a compact JWS. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | id is missing. |
NO_ACCOUNT | There is no account to answer for. |
NOT_FOUND | No receipt of yours has that id. |
OFF | Acting at businesses is not set up on this system yet. |
UNAVAILABLE | This system's records are not available just now. |
pact.business
Your business's PACT setup
For one of your own agents that serves a business: whether people's own agents can act on their accounts there, the permissions it offers (declared with its offerings in its package spec), and the sign-in connected for it, never its secret.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.business({ of_agent: "my-shop" });Rust SDK
let answer = mesh
.pact()
.business(PactBusinessInput {
of_agent: "my-shop".into(),
})
.await?;MCP tool
pact_business
{
"of_agent": "my-shop"
}Command line
agentmesh pact business my-shop
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
of_agent | text | Yes | Your agent's handle or key. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
agent | text | Yes | The agent's key. |
is_business | yes or no | Yes | Whether people's own agents can reach it as a business at all: it has an A2A address, is not an attachment, has no price, and has a default offering. |
why_not | one of: unknown, not_exposed, attachment, priced, no_default_offering | No | When it is not a business, why. unknown: the gateway does not know it. not_exposed: it has no A2A address. attachment: it is an attachment. priced: it charges, and PACT carries no payment. no_default_offering: it has no default offering for a conversation to go to. |
offers_delegation | yes or no | Yes | Whether people's own agents can ask to act on their accounts at it now. |
permissions | list of objects | Yes | The permissions it offers, in its own words. |
permissions[].id | text | Yes | The id. |
permissions[].description | text | Yes | What a person reads before allowing it. |
login | object | No | The sign-in connected for it: its kind, the issuer and the client id. Never the secret. |
login.kind | one of: oidc, reference-test | Yes | oidc: the business's OpenID Connect sign-in. reference-test: the test-only reference login, dev only. |
login.issuer | text | No | The OpenID Connect issuer. |
login.client_id | text | No | The client id. |
login.connected_at | text | Yes | When it was connected. |
redirect_uri | text | Yes | The address to register with your identity provider as the redirect URI. |
card_url | text | Yes | Its PACT card address. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | of_agent is missing. |
NO_ACCOUNT | There is no account to answer for. |
NOT_YOURS | That is not one of your account's agents. |
UNAVAILABLE | The A2A gateway did not answer just now. |
pact.business_login
Connect your business's sign-in
Connect your business's own sign-in to one of your agents, so a person can sign in at your business and allow their agent to act for them there. Register the redirect_uri that business names with your identity provider first, then give its OpenID Connect issuer, the client id and the client secret. The secret is kept like a private key and is never shown again.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.business_login({
of_agent: "my-shop",
issuer: "https://accounts.example.com",
client_id: "shop-agent",
client_secret: "(your client secret)"
});Rust SDK
let answer = mesh
.pact()
.business_login(PactBusinessLoginInput {
of_agent: "my-shop".into(),
issuer: "https://accounts.example.com".into(),
client_id: "shop-agent".into(),
client_secret: "(your client secret)".into(),
})
.await?;MCP tool
pact_business_login
{
"of_agent": "my-shop",
"issuer": "https://accounts.example.com",
"client_id": "shop-agent",
"client_secret": "(your client secret)"
}Command line
agentmesh pact business_login my-shop https://accounts.example.com shop-agent "(your client secret)"
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
of_agent | text | Yes | Your agent's handle or key. |
issuer | text | Yes | The OpenID Connect issuer, an https address. |
client_id | text | Yes | The client id your identity provider gave this connection. |
client_secret | text | Yes | Its client secret. Kept like a private key; never returned. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
login | object | Yes | The sign-in now connected, without its secret. |
login.kind | one of: oidc, reference-test | Yes | oidc: the business's OpenID Connect sign-in. reference-test: the test-only reference login, dev only. |
login.issuer | text | No | The OpenID Connect issuer. |
login.client_id | text | No | The client id. |
login.connected_at | text | Yes | When it was connected. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | A field is missing, the issuer is not https, or its discovery document could not be read. The words say which. |
NO_ACCOUNT | There is no account to answer for. |
NOT_YOURS | That is not one of your account's agents. |
UNAVAILABLE | The A2A gateway did not answer just now. |
pact.business_logout
Disconnect your business's sign-in
Disconnect the sign-in from one of your agents. People's own agents can no longer ask to act on their accounts there; permissions already given stop working when their tokens next renew.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.business_logout({ of_agent: "my-shop" });Rust SDK
let answer = mesh
.pact()
.business_logout(PactBusinessLogoutInput {
of_agent: "my-shop".into(),
})
.await?;MCP tool
pact_business_logout
{
"of_agent": "my-shop"
}Command line
agentmesh pact business_logout my-shop
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
of_agent | text | Yes | Your agent's handle or key. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
removed | yes or no | Yes | True when a sign-in was connected and is now gone. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | of_agent is missing. |
NO_ACCOUNT | There is no account to answer for. |
NOT_YOURS | That is not one of your account's agents. |
UNAVAILABLE | The A2A gateway did not answer just now. |
pact.business_grants
Who allowed agents at your business
The permissions people gave their own agents at one of your agents: the person's id at your business, which personal-agent platform, what they allowed, since when, and whether it has ended. No token is ever shown.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.business_grants({ of_agent: "my-shop" });Rust SDK
let answer = mesh
.pact()
.business_grants(PactBusinessGrantsInput {
of_agent: "my-shop".into(),
})
.await?;MCP tool
pact_business_grants
{
"of_agent": "my-shop"
}Command line
agentmesh pact business_grants my-shop
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
of_agent | text | Yes | Your agent's handle or key. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
grants | list of objects | Yes | Each permission given there. |
grants[].grant_id | text | Yes | Its id, to end it. |
grants[].person | text | Yes | The person's id at your business, from your sign-in. |
grants[].personal_agent | text | Yes | The personal-agent platform that holds it, by its issuer. |
grants[].permissions | list of text | Yes | What they allowed. |
grants[].since | text | Yes | When. |
grants[].ends | text | Yes | When it runs out. |
grants[].ended | text | No | When it was ended, if it was. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | of_agent is missing. |
NO_ACCOUNT | There is no account to answer for. |
NOT_YOURS | That is not one of your account's agents. |
UNAVAILABLE | The A2A gateway did not answer just now. |
pact.business_end_grant
End a person's permission at your business
End one permission at one of your agents at once: the token the person's agent holds is refused on its next use.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.business_end_grant({
of_agent: "my-shop",
grant_id: "pactgrant_0123456789abcdefghijklmn"
});Rust SDK
let answer = mesh
.pact()
.business_end_grant(PactBusinessEndGrantInput {
of_agent: "my-shop".into(),
grant_id: "pactgrant_0123456789abcdefghijklmn".into(),
})
.await?;MCP tool
pact_business_end_grant
{
"of_agent": "my-shop",
"grant_id": "pactgrant_0123456789abcdefghijklmn"
}Command line
agentmesh pact business_end_grant my-shop pactgrant_0123456789abcdefghijklmn
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
of_agent | text | Yes | Your agent's handle or key. |
grant_id | text | Yes | The permission's id, from business_grants. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
ended | yes or no | Yes | True when it was live and is now ended. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | A field is missing. |
NO_ACCOUNT | There is no account to answer for. |
NOT_YOURS | That is not one of your account's agents, or the permission is not at it. |
UNAVAILABLE | The A2A gateway did not answer just now. |
pact.platforms
Personal-agent platforms the gateway accepts
The personal-agent platforms AgentMesh's A2A gateway accepts on this system, and the audience it assigns them all. This system's own personal agent is accepted without a record.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.platforms();
Rust SDK
let answer = mesh
.pact()
.platforms(PactPlatformsInput::default())
.await?;MCP tool
pact_platforms
{}Command line
agentmesh pact platforms
What you send
You send nothing.
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
audience | text | Yes | The audience every platform puts in its tokens for this gateway. |
platforms | list of objects | Yes | Each platform listed. |
platforms[].id | text | Yes | The record's id. |
platforms[].issuer | text | Yes | The platform's issuer. |
platforms[].jwks_uri | text | Yes | Where its keys are. |
platforms[].name | text | Yes | Its name. |
platforms[].enabled | yes or no | Yes | Whether its tokens are accepted. |
Refusals
| Code | What it means |
|---|---|
NOT_OPERATOR | Only an operator may see this, with an operator key carrying the pact scope. |
UNAVAILABLE | The A2A gateway did not answer just now. |
pact.platform_add
Accept a personal-agent platform
List a personal-agent platform with AgentMesh's A2A gateway: its issuer, matched exactly, and where its public keys are. Tell the platform the audience this answers with.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.platform_add({
issuer: "https://pa.example/pact",
jwks_uri: "https://pa.example/pact/.well-known/jwks.json",
name: "Example personal agents"
});Rust SDK
let answer = mesh
.pact()
.platform_add(PactPlatformAddInput {
issuer: "https://pa.example/pact".into(),
jwks_uri: "https://pa.example/pact/.well-known/jwks.json".into(),
name: "Example personal agents".into(),
})
.await?;MCP tool
pact_platform_add
{
"issuer": "https://pa.example/pact",
"jwks_uri": "https://pa.example/pact/.well-known/jwks.json",
"name": "Example personal agents"
}Command line
agentmesh pact platform_add https://pa.example/pact https://pa.example/pact/.well-known/jwks.json "Example personal agents"
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
issuer | text | Yes | The platform's issuer, exactly as its tokens carry it. |
jwks_uri | text | Yes | Where its public keys are, an https address. |
name | text | Yes | Its name, for people. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
platform | object | Yes | The record. |
platform.id | text | Yes | The record's id. |
platform.issuer | text | Yes | The platform's issuer. |
platform.jwks_uri | text | Yes | Where its keys are. |
platform.name | text | Yes | Its name. |
platform.enabled | yes or no | Yes | Whether its tokens are accepted. |
audience | text | Yes | The audience to tell the platform. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | A field is out of shape, or the platform is listed already. The words say which. |
NOT_OPERATOR | Only an operator may do this, with an operator key carrying the pact scope. |
UNAVAILABLE | The A2A gateway did not answer just now. |
pact.platform_set
Change a personal-agent platform
Turn a listed platform off or on, rename it, or point it at new keys.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.platform_set({
id: "0f6c2d3e-1a2b-4c5d-8e9f-0a1b2c3d4e5f",
enabled: false
});Rust SDK
let answer = mesh
.pact()
.platform_set(PactPlatformSetInput {
id: "0f6c2d3e-1a2b-4c5d-8e9f-0a1b2c3d4e5f".into(),
enabled: Some(false),
..Default::default()
})
.await?;MCP tool
pact_platform_set
{
"id": "0f6c2d3e-1a2b-4c5d-8e9f-0a1b2c3d4e5f",
"enabled": false
}Command line
agentmesh pact platform_set 0f6c2d3e-1a2b-4c5d-8e9f-0a1b2c3d4e5f
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
id | text | Yes | The record's id, from platforms. |
enabled | yes or no | No | Off refuses its tokens at once. |
jwks_uri | text | No | New keys address, https. |
name | text | No | New name. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
platform | object | Yes | The record now. |
platform.id | text | Yes | The record's id. |
platform.issuer | text | Yes | The platform's issuer. |
platform.jwks_uri | text | Yes | Where its keys are. |
platform.name | text | Yes | Its name. |
platform.enabled | yes or no | Yes | Whether its tokens are accepted. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | A field is out of shape. |
NOT_FOUND | No platform has that id. |
NOT_OPERATOR | Only an operator may do this, with an operator key carrying the pact scope. |
UNAVAILABLE | The A2A gateway did not answer just now. |
pact.platform_remove
Stop accepting a personal-agent platform
Take a platform off the list: its tokens are refused at once.
Here is the same request on each door.
TypeScript SDK
const answer = await mesh.pact.platform_remove({ id: "0f6c2d3e-1a2b-4c5d-8e9f-0a1b2c3d4e5f" });Rust SDK
let answer = mesh
.pact()
.platform_remove(PactPlatformRemoveInput {
id: "0f6c2d3e-1a2b-4c5d-8e9f-0a1b2c3d4e5f".into(),
})
.await?;MCP tool
pact_platform_remove
{
"id": "0f6c2d3e-1a2b-4c5d-8e9f-0a1b2c3d4e5f"
}Command line
agentmesh pact platform_remove 0f6c2d3e-1a2b-4c5d-8e9f-0a1b2c3d4e5f
What you send
| Field | Type | Required | What it means |
|---|---|---|---|
id | text | Yes | The record's id, from platforms. |
What comes back
| Field | Type | Always there | What it means |
|---|---|---|---|
removed | text | Yes | The id removed. |
Refusals
| Code | What it means |
|---|---|
INPUT_INVALID | id is missing. |
NOT_FOUND | No platform has that id. |
NOT_OPERATOR | Only an operator may do this, with an operator key carrying the pact scope. |
UNAVAILABLE | The A2A gateway did not answer just now. |
A real example
This request, pact.send, was sent on 2026-10-07 to the AgentMesh development system, by the test-rig account with an account API token made for the one call, to the made-up shop in AgentMesh's PACT demo.
It sent this through the MCP tool:
pact_send {"card_url":"https://a2a.dev.agentmesh.ai/a2a/UDWPBUNXKWZGPZVULJB3DYZSMDOUETC7U5LSFI45CX5WAM5LAXPLAQ3L/.well-known/agent-card.json","text":"Where is my order LG-1042?","new_conversation":true}
The platform answered:
{
"business": "larkspur-goods",
"kind": "reply",
"reply": "Order LG-1042, a linen throw and two candles, shipped by ground. It is on its way and should arrive within three days.",
"conversation": "ac46153d-6125-48e8-bab1-32d727a9e05a",
"offers_delegation": true,
"acting_for_you": true,
"receipt": {
"verified": true,
"scopes_used": [],
"actions": []
},
"card_url": "https://a2a.dev.agentmesh.ai/a2a/UDWPBUNXKWZGPZVULJB3DYZSMDOUETC7U5LSFI45CX5WAM5LAXPLAQ3L/.well-known/agent-card.json"
}
What uses it
| What uses it | What for |
|---|---|
| A person's agent | It asks a business's agent about an order, a booking or an account, and carries on the conversation, through this request. |
| The app's Connections page | It lists the businesses your agent can act at, with what each allows and the business's signed receipts, and ends a permission with Revoke. |
| A business's owner | They connect their business's own sign-in to their agent, see the permissions it offers, and end a person's permission, through the business requests, on their agent's page in the app or from their own code. |
| AgentMesh's operators | They list, add and turn off the personal-agent platforms AgentMesh's A2A gateway accepts, through the platform requests. |
Versions and old names
| Version | Date | What changed |
|---|---|---|
| 1 | 2026-10-06 | The first definition: send. |
| 2 | 2026-10-07 | PACT Delegated: connect asks a business for permission to act for you; send carries that permission, says whether it did, and returns the business's checked receipt. |
| 3 | 2026-10-07 | The person's grants and receipts (grants, end_grant, receipts, receipt); a business owner's sign-in connection, permissions and grants (business, business_login, business_logout, business_grants, business_end_grant); and the operators' list of personal-agent platforms (platforms, platform_add, platform_set, platform_remove). |
| 4 | 2026-10-07 | business says whether the agent serves people's own agents as a business at all (is_business) and, when it does not, why (why_not); grants gives each permission in the business's own words (allowed); the app makes the person's and the owner's requests where the person is signed in. |
None of its requests had another name before, so there are no old names to stop.