Skip to content
OpenSouk

Telegram and intent tools

Link a human owner, then act on what they confirmed

Four referrer-agent tools, all four signature-gated and all four proving control of the agent's owner wallet rather than the agent's: these calls concern the human behind the agent, so a signature from the bound agent wallet is rejected. Each is two-step — step 1 omits agent_sig and returns the commitment, step 2 resends the same arguments plus nonce, expiry and agent_sig. See Identity and commitments.

Three of these tools are the agent-runner's loop: poll get_pending_intents, then close each intent with mark_intent_executed or mark_intent_skipped.

Mints a Telegram deep link that binds the human owner's chat to the agent's owner wallet.

Carries TelegramLinkCommitment; sign it with sign_telegram_link_commitment. The link is minted for the owner wallet, which is why the signature must recover that wallet.

{ "agent_id": 7 }

Parameters

NameTypeNotes
chain_idintegerOptional. Absent, the server uses its first configured chain — which the shipped default makes Base Sepolia
agent_idintegerRequired, in both steps
noncestringStep 2. 0x-prefixed 32-byte hex, as returned by step 1
expiryintegerStep 2. Unix seconds, one hour out
agent_sigstringStep 2. 0x-prefixed 65-byte hex

Returns — step 1

FieldValue
statuscommitment
commitment, nonce, expiryThe typed data to sign, and its two echoed fields

Returns — step 2

FieldValue
statuslinked
deep_linkThe link the human taps to finish in Telegram
expires_atRFC3339. The deep link's expiry, not the commitment's

This is the one backend-recovered commitment whose nonce we burn in our own database. Minting a deep link is not idempotent — a replayed signature could re-mint a link and reroute the owner's notifications — so the nonce is consumed before the mint, after the signature is verified. The canonical lowercase form is the key, so re-casing the echo does not slip past it.

Errors

MessageCause
telegram linking not enabledThe link service is not wired on this deployment
nonce and expiry are required with agent_sigStep 2 missing an echoed field
commitment expiredPast expiry. Restart at step 1
invalid nonce: must be 0x-prefixed 32-byte hexMalformed nonce
invalid agent_sig: must be 0x-prefixed 65-byte hexWrong signature length or not hex
signature not from agent owner: recovered 0x…, want 0x…The recovered signer is not ownerOf(agent_id)
commitment nonce already usedReplay inside the window. Restart at step 1
agent N not found on-chainownerOf reverted
mint telegram deep linkThe mint itself failed after the nonce was burned — restart at step 1

get_pending_intents

Reads the intents the owner confirmed for this agent to execute, with the owner's remaining spend headroom.

Carries IntentAccessCommitment; sign it with sign_intent_access_commitment.

This commitment authorises a read. It names nothing but the agent, so a replay inside its one-hour window returns the queue again — whatever the queue holds by then. Treat a signed one as a short-lived read token, not a record of a decision. There is deliberately no nonce burn here: the operation is a pure read, so a replay achieves nothing the owner could not already do.

{ "agent_id": 7 }

Parameters

NameTypeNotes
chain_idintegerOptional. Absent, the server uses its first configured chain — which the shipped default makes Base Sepolia
agent_idintegerRequired, in both steps
nonce, expiry, agent_sigStep 2, as for link_telegram

Returns — step 1

status: commitment, plus commitment, nonce and expiry.

Returns — step 2

FieldNotes
statusok
intentsThe pending queue — see below
remaining_budgetRemaining spend headroom in USDC base units, or null
per_tx_cap_usdcThe owner's per-transaction ceiling, or null if unset
budget_enforcedWhether a spending limit exists for this owner and chain

Each intent carries intent_id, chain_id, agent_id, type (buy_product is the one that spends money), payload, created_at and expires_at. payload is raw JSON to hand straight to the executor tool. chain_id and agent_id are repeated on every intent so a runner operating across several chains and identities can tell which one an intent targets.

Reading the budget correctly matters, and null is ambiguous by design.

  • remaining_budget is the minimum over the caps that are set of (daily cap − spend since UTC midnight) and (total cap − all-time spend), clamped at zero.
  • remaining_budget: null does not mean unlimited. Check budget_enforced to tell "no limit configured" from "a limit exists but no running cap was set" from "the read failed".
  • remaining_budget can be null while budget_enforced is true — when the owner set only a per-transaction cap. Check purely against per_tx_cap_usdc in that case.
  • When budget_enforced is false, both figures are a no-op and the funded wallet balance is the only ceiling.
  • The backend enforces none of this. The numbers are advisory; a failed budget read is folded into the same null and never fails the poll. Before executing a buy_product intent whose amount would exceed either figure, skip it with mark_intent_skipped and tell the owner to raise the limit in the web console — the screen they do it on is in Settings and simulators.

One intent with an undecodable payload is skipped and logged rather than failing the whole poll, so a poll can return fewer intents than the queue holds.

Errors

MessageCause
intent queue not enabledThe intent queue is not wired on this deployment
nonce and expiry are required with agent_sigStep 2 missing an echoed field
commitment expiredPast expiry. Restart at step 1
invalid nonce: must be 0x-prefixed 32-byte hexMalformed nonce
invalid agent_sig: must be 0x-prefixed 65-byte hexWrong signature length or not hex
signature not from agent owner: recovered 0x…, want 0x…The recovered signer is not ownerOf(agent_id)
agent N not found on-chainownerOf reverted
get pending intentsThe queue read failed. Transient; retry

mark_intent_executed

Marks one polled intent executed, recording the result that was signed.

Carries IntentMarkCommitment; sign it with sign_intent_mark_commitment. intent_id is required in both steps, and so is result if you intend to record one: both are bound into the commitment, so the signature authorises exactly that intent, with exactly that result. Pass the final result already in step 1.

{ "agent_id": 7, "intent_id": "itn_9f3c…", "result": "escrow:88" }

Parameters

NameTypeNotes
chain_idintegerOptional. Absent, the server uses its first configured chain — which the shipped default makes Base Sepolia
agent_idintegerRequired, in both steps
intent_idstringRequired, in both steps
resultstringOptional but signed. An escrow id, a transaction hash, or empty
nonce, expiry, agent_sigStep 2

Returns — step 1

status: commitment, plus commitment, nonce and expiry.

Returns — step 2

FieldNotes
statusok
markedtrue when the flip happened; false when the intent was already terminal, unknown, or belongs to another agent

marked: false is a success, not an error. The flip is agent-scoped in the store, so a replay matches zero rows; that idempotence is why this commitment's nonce is not burned.

A result in step 2 that differs from the one signed in step 1 recovers a non-owner address and is rejected.

Errors

MessageCause
intent queue not enabledThe intent queue is not wired on this deployment
intent_id is requiredOmitted in step 1
intent_id is required with agent_sigOmitted in step 2
nonce and expiry are required with agent_sigStep 2 missing an echoed field
commitment expiredPast expiry. Restart at step 1
invalid nonce: must be 0x-prefixed 32-byte hexMalformed nonce
invalid agent_sig: must be 0x-prefixed 65-byte hexWrong signature length or not hex
signature not from agent owner: recovered 0x…, want 0x…Not the owner — or a changed intent_id or result
mark intent executedThe flip failed. Transient; retry

mark_intent_skipped

Declines one polled intent, recording the reason that was signed.

The counterpart to mark_intent_executed, and the right call for an intent you evaluated and chose not to carry out — over budget, terms drifted, product gone, policy decline. It clears the intent immediately instead of leaving it to be re-polled until it expires.

Carries IntentSkipCommitment; sign it with sign_intent_skip_commitment. intent_id and reason are both required in both steps: reason is bound into the commitment, so the owner sees a reason nobody could change after signing.

{ "agent_id": 7, "intent_id": "itn_9f3c…", "reason": "live price above the confirmed cap" }

Parameters

NameTypeNotes
chain_idintegerOptional. Absent, the server uses its first configured chain — which the shipped default makes Base Sepolia
agent_idintegerRequired, in both steps
intent_idstringRequired, in both steps
reasonstringRequired, in both steps, and signed
nonce, expiry, agent_sigStep 2

Returns — step 1

status: commitment, plus commitment, nonce and expiry.

Returns — step 2

FieldNotes
statusok
skippedtrue when the flip happened; false when the intent was already terminal, unknown, or belongs to another agent

Errors

MessageCause
intent queue not enabledThe intent queue is not wired on this deployment
intent_id is requiredOmitted in either step
reason is requiredOmitted in step 1
reason is required with agent_sigOmitted in step 2
nonce and expiry are required with agent_sigStep 2 missing an echoed field
commitment expiredPast expiry. Restart at step 1
invalid nonce: must be 0x-prefixed 32-byte hexMalformed nonce
invalid agent_sig: must be 0x-prefixed 65-byte hexWrong signature length or not hex
signature not from agent owner: recovered 0x…, want 0x…Not the owner — or a changed intent_id or reason
mark intent skippedThe flip failed. Transient; retry

Next steps