KYB developer guide
Early access. Security controls are in place. Tool names, input fields, and documentation may change as we incorporate feedback.
This guide shows the shortest working path for business verification: connect an MCP client, find the correct business, verify it, and retrieve the report. Start with sandbox data. Move to live verification only after the flow works end to end.
Before you start
- An MCP client that supports streamable HTTP.
- A business name and country, or a known registration number.
- Start in sandbox so you can test the full flow without billing.
The flow
- Connect. Add
https://mcp.trulioo.com/mcpto your MCP client and complete OAuth. - Find the business. Search by name, or look up the registration rules for the country.
- Confirm the candidate. If search returns more than one business, ask the user to choose before you verify.
- Verify. Call
kyb_verifywith the selected registration identifier. - Handle the result. Follow
next_actionwhen the result is not terminal. Save the transaction ID. - Retrieve the report. Call
kyb_get_reportafter verification completes.
Tools used in this guide
| Search for a business | kyb_search · Tools → |
| Look up registration details | kyb_registration_lookup · Tools → |
| Verify a business | kyb_verify · Tools → |
| Retrieve a completed report | kyb_get_report · Tools → |
Zero to verified
Early access. Security controls are in place. Tool names, input fields, and documentation may change as we incorporate feedback.
One MCP connection gives any agent KYC, KYB, and Know Your Agent - the signed identity an agent carries so anyone can prove who is behind it. There is no key to copy-paste - your client enrols itself over OAuth. Here is the whole path.
- Connect the MCP server. Point any MCP client at the hosted endpoint - it discovers the authorization server and registers itself, so there is no key to copy-paste. Client setup →
- Call a verification tool. Run
kyc_verifyorkyb_verifyagainst synthetic test entities and branch on the typed result. Tools → - Give your agent an identity. Verify the organization behind the agent, then mint a signed, scoped attestation with
kya_issue_mandate. Know Your Agent → - Let anyone verify it. Publish the attestation in your A2A card; any party checks it against the issuer JWKS - no key needed. Verify agents →
I want to…
| Verify a person | kyc_verify · Tools → |
| Verify a business | kyb_verify · Tools → |
| Screen a name on its own | aml_screen - per-account · Tools → |
| Capture a document or a selfie | docv_create_session - per-account · Tools → |
| Prove who is behind an agent | Know Your Agent → |
| Verify another agent's profile (DAP) | kya_verify_agent · Verify agents → |
| Connect an MCP client | Client setup → |
| Authenticate with OAuth | Authentication → |
| Have an agent set this up for me | Let your agent introduce you → |
| Read the docs as an agent | index.md · llms.txt |
Let your agent guide your KYB setup
Paste this into your coding agent. It will check the current connection before asking you to configure anything, then guide one sandbox business verification from discovery through report retrieval.
Paste this to your agent
agent-guide.md is a focused operating guide for this early access workflow. It covers connection checks, OAuth, business search, optional candidate confirmation, verification, non-terminal results, and report retrieval.
It checks before it acts. The guide first looks for an existing Trulioo connection and confirms the session mode. It starts verification only after the developer confirms the correct business.
The MCP endpoint
One hosted endpoint, spoken over MCP streamable HTTP. Any MCP-compatible client or agent framework connects to the same URL - one integration for your whole fleet.
Endpoint
One endpoint, two connection modes. Use the client-managed OAuth consent
flow for sandbox testing. For a live integration, exchange your Trulioo
client_id and client_secret for an MCP access token before
connecting to the same endpoint.
Authentication
/mcp requires an access token. Start with the sandbox
connection to validate your KYB workflow. When your account is approved for live use,
bootstrap a live token with your Trulioo client credentials.
Sandbox connection
Claude Code, Cursor, Codex, and ChatGPT use the client-managed OAuth 2.1 + PKCE flow:
- Add
https://mcp.trulioo.com/mcpto the client. - The client discovers Trulioo authorization and opens the consent flow.
- Choose sandbox.
- The client initializes the MCP session and loads the tools available to that connection.
Let the client manage sandbox OAuth. Do not copy sandbox tokens, register a client by hand, or hardcode authorization endpoints.
Start in sandbox
Sandbox uses the same endpoint and tool schemas as live access. It is unbilled and intended for testing the
full integration before you work with production data. Sandbox results include a test_mode
marker so your application can identify them.
Live integration with client credentials
For an approved live account, store the Trulioo client_id and
client_secret in your secret manager or environment. Send them only to the
token bootstrap endpoint over TLS.
Request an MCP access token
Response
The bootstrap validates the credentials with Trulioo, holds the upstream credential
server-side, and returns a short-lived MCP access token. Store the returned
access_token in TOKEN; the Raw JSON-RPC client setup below shows
the complete initialization sequence.
- Never send
client_secretto/mcp, place it in a URL, or log it. - The bootstrap does not return a refresh token. Re-run the bootstrap when the MCP
access token expires or the server returns
401. 401 invalid_clientmeans the credentials were malformed or rejected. Retry only after checking the credential configuration.- If Trulioo authentication is temporarily unavailable, retry the bootstrap with bounded backoff.
Usage limits
Usage limits apply and may change during early access. If a result includes
retry_after_seconds, wait for that interval before retrying. Contact Trulioo before a
production-scale rollout so limits can be reviewed for your use case.
Client setup
Pick your client and point it at the hosted endpoint. Use its OAuth flow for sandbox. For live use, the client must support sending the bearer token returned by the client-credentials bootstrap.
Add the endpoint
That single line is the whole setup - the client registers itself over OAuth. It gives you the tools, and nothing else.
Add to your MCP client config
Works with any client that reads a standard MCP server config (Cursor, VS Code, Claude Desktop, and more).
OpenAI Codex CLI - add by URL
ChatGPT (Developer mode) - add the server by URL
ChatGPT connects over OAuth 2.1 with PKCE and dynamic client registration. The consent screen selects sandbox or approved live access.
Discover the tools an agent can call
This is a real MCP session, not a REST API: initialize first, keep the
mcp-session-id the server hands back, and send it on every later call. A bare
tools/list is refused with 422 Unexpected message, expect initialize request
even when your token is perfectly good. An MCP client does all of this for you - you only need the
sequence below if you are speaking the protocol by hand.
Responses come back as Server-Sent Events, so parse data: lines rather than expecting one
JSON body - that is what -N and the text/event-stream accept header are for.
Without the bearer token the first call returns 401 plus a WWW-Authenticate
header pointing at the authorization server. How to get a token →
Going live does not change the MCP URL. It changes how the bearer token is obtained:
use the approved account's client_id and client_secret at
/oauth/token.
Authentication →
KYB tools reference
Tools reference
The KYB surface is a typed sequence: discover the business,
resolve ambiguity, verify it, poll when needed, and fetch the report.
tools/list remains the authority for the tools available to your account.
Every capability is a typed, discoverable MCP tool - schema-enforced inputs,
structured results agents branch on, and no raw passthrough - a tool that is not on your connection is not
reachable by another route. A default progressive connection advertises 17 resident tools and exposes a
default union of 42 tools through runtime discovery. Per-account families change the enabled set. The exact
resident set is what tools/list returns for
your connection, so discover it rather than hardcoding this list.
Example: call a tool over JSON-RPC
Both headers are required: $TOKEN from
Authentication, and $SID from the
initialize handshake - see Raw JSON-RPC under Client
setup.
KYB workflow and responses
Identity & business verification
| Step | Tool | Use it when | Response and next step |
|---|---|---|---|
| 1 | kyb_search |
You have a business name but not a confirmed registration identifier. | Returns: search_summary with candidate_count, has_results, and top_matches. Confirm a candidate before verification; do not use the top-level RecordStatus to decide whether matches were found. |
| As needed | kyb_registration_lookup |
You need the registration types or jurisdiction details accepted for a country. | Returns: supported registration-number types or jurisdictions of incorporation. Use them to format the search or verification input. |
| As needed | kyb_disambiguate_candidate |
Search returns multiple businesses and the user must choose the correct one. | Returns: resolved, candidate_index, and the selected candidate. Clients without interactive selection receive numbered options. Continue only after confirmation. |
| 2 | kyb_verify |
You have confirmed the business and are ready to start verification. | Returns: transaction_id, record_id, status, is_terminal, and next_action. Branch on status; follow next_action when the result is not terminal. |
| While running | kyb_get_partial_result |
The verification is still running and you need the latest available state. | Returns: the latest available verification fields plus is_terminal and next_action. Continue polling only while the result is not terminal. |
| 3 | kyb_get_report |
The verification is complete and you need the final report. | Returns: a structured report, or a PDF descriptor with record_id, report_available, content_type, and resource_uri. Store the report reference with the transaction. |
| Reference | transaction_lookup |
You need to retrieve a previous verification from its transaction identifier. | Returns: the matching record and identity context for a TransactionID or TransactionRecordID. Use the resolved record for status or report retrieval. |
| Tool | Does |
|---|---|
kyc_verify | Verify a person across 195+ countries; returns match / review / nomatch + next-action hints. |
kyc_get_status / kyc_get_record | Poll an async verification, then fetch the completed record. |
kyb_verify | Verify a business, with UBO discovery and due-diligence sequencing. |
kyb_search / kyb_get_report | Find a business, then retrieve its full report. |
kyb_registration_lookup | Registration numbers + jurisdictions of incorporation (routes by the args you pass). |
kyb_disambiguate_candidate | When a search returns several businesses, have the user pick which one before verifying (interactive on clients that support it, else numbered options to confirm inline). |
kyb_get_partial_result | Fetch partial results for a long-running KYB job. |
transaction_lookup | Look up a past KYC/KYB verification by the transactionId you already hold - resolves a TransactionID or TransactionRecordID to the record + identity. |
Per-account families
Off unless your account is entitled to them, each enabled on its own. They are real and supported;
they are simply absent from tools/list until your deployment has them. Ask Trulioo for the
families you need rather than coding around them, and read the result from tools/list -
getting one family does not get you the rest.
| Tool | Does |
|---|---|
aml_screen | Standalone sanctions and PEP screening for a name you are not verifying. |
docv_create_session | Start a document + liveness capture session. Returns a session_url the person opens; images and biometric data never cross the MCP stream. |
docv_get_result | Read the outcome of a capture session. Returns a Task to a tasks-capable client; otherwise poll. |
docv_cancel_session | Cancel a capture session the person abandoned. |
docv_create_mobile_handoff | Hand a desktop session off to the person's phone for the camera step. |
age_check | Age assurance from a known date of birth. Its sibling age_estimate_biometric is declared but returns NotImplemented until biometric estimation ships - do not build against it. |
monitoring_enroll | Put a verified subject under ongoing monitoring. |
monitoring_get_alert | Read an alert monitoring raised. |
monitoring_refresh | Re-run the checks behind an enrollment now. |
monitoring_cancel | End an enrollment. |
monitoring_get_enrollment | Read an enrollment's current state. |
Alpha tier - internal and alpha customers only. A single switch,
TRULIOO_EXPERIMENTAL=true, turns on four families at once - ownership graph, deep
research, document verification and standalone AML screening - taking the fully enabled union from
42 tools to 50 tools. A per-family variable still wins in both directions, so TRULIOO_ENABLE_DOCV=false
beside it holds document verification back. Age assurance and ongoing monitoring are not in
the tier; they stay individually entitled. It does not reach the host-rendering surfaces
(TRULIOO_ENABLE_A2UI, TRULIOO_ENABLE_MCP_APPS), which a client negotiates
rather than an account entitles. On a hosted connection this is an operator-set deployment variable,
not something a client can ask for. Post-KYB work starts through
kyb_run_follow_up; poll Deep Research with kyb_get_research or a streamed
ownership walk with ubo_get_graph. Direct starts are not exposed.
tools/list and config_discover_account are the authority on what your
connection has. Do not hardcode the list above, and do not synthesize a tool name that is not on it -
there is no raw passthrough, so a tool that is absent is not reachable by another route.
Know Your Agent
| Tool | Does |
|---|---|
kya_admission_challenge | Mint a short-lived, single-use enterprise admission challenge for one privileged target tool. The returned token is bound to the authenticated tenant, session, target tool, and policy version. |
kya_possession_challenge | Mint the single-use nonce a keyed card's possession proof must carry. Call this first - kya_issue_mandate rejects a proof without a fresh nonce. On a software key this proof is also what earns AAL2; tier alone does not. |
kya_issue_mandate | One call: verify the organization → register the agent → sign a scoped attestation → anchor it. Returns the attestation JWS + the A2A extension block. |
kya_verify_agent | Verify another agent's card; optionally check a requested_action against its signed scope (the scoped handshake). |
kya_lookup | Public lookup of an agent's standing by DAP handle or fingerprint. depth selects the tier: lookup (free, is it verified and who is it) or verify (paid, adds advisory signals). |
kya_card_fingerprint | Compute a card's fingerprint before you register it - answers “will this build keep my passport?”. Costs nothing and spends no issuance - pure arithmetic over the card you supply - but it needs your account key like the rest of the keyed surface: it is a build-time developer utility, not a relying-party read. It names which fields are identity-bearing (name, the first interface URL, code_digest, and the agent_key thumbprint - so rotating your key re-mints too) and which are free to change. Returns no trust verdict. |
kya_verify_web_bot_auth | Verify a Web Bot Auth (RFC 9421) signed HTTP request and resolve it to the agent behind it. Note a bare, replayable signature is AAL1 even at tier 2. |
kya_verify_protocol | Verify a rail-specific envelope (UCP / AP2 / ACP / x402). A2A cards use kya_verify_agent. |
kya_supersede_agent | Rotate an agent's key or reissue its profile, superseding the prior credential so verifiers follow the replacement. |
kya_retire_agent | Revoke standing for a retired or compromised agent. A verifier resolving its lookup sees the credential is no longer good. |
kya_verify_mandate | Verify a mandate credential a counterparty presented to you - signature, issuer, validity window, and with freshness: central_fresh its revocation status. Reach for this rather than kya_get_mandate whenever somebody hands you a credential: reading a mandate by an id lifted out of an unverified document trusts the document to describe itself. Pass amount to also learn whether the sum you are about to authorize sits inside the ceiling the credential declares - advisory only, and it never changes valid. An amount_advisory.within of null means unanswerable, never a pass. |
kya_get_mandate | Read a mandate you issued: status, validity window, and the signed scope - allowed actions, merchants, and the spend cap. A max_amount of null means uncapped, never a cap of zero. |
kya_record_spend | Record a settled spend against a mandate, which is what makes a day/total ceiling answerable at all. Your settlement_id is the de-duplication key: replaying it with the same amount returns recorded: false and counts once, while the same id with a different amount is refused 409 rather than silently overwritten. Recording is not enforcement - it moves no money and blocks nothing. |
kya_mandate_spend | Read a mandate's spend ledger: the running totals per currency, the declared ceiling, and the headroom left. A remaining of null is not zero - it means there is no headroom to speak of, either uncapped or a per-transaction cap, which limits each purchase rather than depleting. |
kya_revoke_mandate | Revoke one mandate, with a reason recorded for the audit trail. The capability rails fail closed on the next verify; the A2A discovery tier is OfflineOk by design, so it lags until the credential expires. |
kya_revocations | List the mandates already revoked, with the status-list index each one occupies - the bulk read behind a verifier's own cache. |
kya_transparency_sth | Fetch the signed tree head: tree size, root hash, and the issuer's signature over both. The anchor every inclusion proof hangs from. Public - no account needed. |
kya_inclusion_proof | Prove a leaf sits under a signed root (RFC 6962). Public - no account needed. Verify the returned audit path with verify_inclusion_hashed, not verify_inclusion: the served leaf_hash is already hashed, and hashing it twice reports a sound log as broken. |
kya_status_list | Fetch the signed status list as its compact JWS (application/statuslist+jwt) - the revocation bitstring a verifier checks offline. Public. Re-signed per request with a fresh validFrom, so do not cache or diff it by byte hash. |
kya_rails | What each rail demands before you build for it: expected_typ, tier, freshness, binding, signing alg, schema URL, and the issuer JWKS to resolve keys from. Public. |
kya_assess_readiness | Measure the public agent-facing documents a host publishes and return evidence-backed reason codes and residuals. It reports no score or grade and requires account credentials. |
kya_assess_artifact | Submit one immutable software release or exact Git commit for a tenant-scoped multi-collector assessment. The selected collector portfolio is frozen with the subject and policy. The operation reports lifecycle and coverage intent, not a vendor score, grade, rank, or allow decision. |
kya_assessment_status | Read one assessment's lifecycle and frozen collector coverage. Partial, failed, canceled, expired, and unavailable never mean clean. Admitted evidence and KYA signals are exposed only when the assessment contract supports them. |
kya_verify_client | Verify a Client ID Metadata Document before admitting an OAuth client: fetch the https URL that is its client_id under MCP 2026-07-28, validate it against draft-ietf-oauth-client-id-metadata-document-00, and get back the document's origin, its redirect_uris, whether it publishes a key (jwks_uri + private_key_jwt) or is a public client, and any KYA operator claim it carries. Runs the same SSRF-hardened fetch the authorization server runs, so the verdict predicts admission. Two tier fields, deliberately: record_trust_tier is a statement about the URL, request_trust_tier_ceiling is the most a request carrying that client_id could reach - binding the first to a request is the mistake this shape exists to prevent. The carried attestation is never verified here (attestation_verified is always false); the issuer is the source of truth, so follow up with kya_lookup on the fingerprint. |
kya_register_artifact | Register a complete software artifact package as an immutable release candidate. The server verifies publisher binding and computes package and distribution digests without publishing it. |
kya_publish_artifact | Publish a registered software-artifact release candidate using an audited, optimistic-concurrency transition. |
kya_revoke_artifact | Permanently revoke a compromised software-artifact release. This audited transition is destructive and irreversible. |
Discovery, meta & workflow prompts
| Tool | Does |
|---|---|
trulioo_tool_schema | Read a tool's full input schema and complete authored guidance (up to 8 at a time). The tool list carries a one-line description to keep a client's cold start small; this is where the operational detail lives - required fields per country, which flag actually starts an ownership walk, which result fields are advisory rather than evidence. |
trulioo_find_tools / trulioo_invoke_tool | Progressive discovery, advertised only when TRULIOO_TOOL_DISCOVERY=progressive. The server then lists a 15-tool resident core (~2.2k tokens instead of ~6.4k) and keeps the rest reachable: trulioo_find_tools searches the manifest by keyword or family, trulioo_invoke_tool calls a tool that is not listed. Dispatch passes the same profile, family, rate-limit, circuit-breaker and KYA gates as a direct call, cannot widen a profile or re-enable a disabled family, and refuses destructive verbs - those stay advertised so your client always sees their approval hints. |
config_discover_account, config_describe_context, and
config_list_test_entities tell an agent what its account can do and which safe test
subjects it can use before it starts a KYB flow. trulioo_health and
webhook_journal cover liveness and async callbacks. The
kyb_due_diligence_workflow prompt sequences search, disambiguation, verification, and
screening; prompts/list is the authority on the set your connection offers.
trulioo_capabilities and trulioo_getting_started let an agent self-orient.
config_discover_account, config_describe_context, and
config_list_test_entities tell an agent what its account can do and which safe test
subjects it can use before it asks a user for anything. trulioo_health and
webhook_journal cover liveness and async callbacks. Guided workflow
prompts (kyc_onboarding_workflow, kyb_due_diligence_workflow) sequence the
multi-step flows; prompts/list is the authority on the set your connection offers.
trulioo_capabilities and trulioo_getting_started let an
agent self-orient. There is no raw passthrough: every upstream call goes through a typed tool, so a
tool that is not on your connection is not reachable by another route.
Protocol capabilities (negotiated per connection)
The revision is negotiated at initialize: the floor is 2025-06-18 and the
newest draft the server supports is 2026-07-28. Features land only for a client that
asked for the revision carrying them - everything else degrades to the floor behavior, so read the
negotiated value back from trulioo_capabilities rather than assuming one. Two optional
extensions a capable client can opt into:
Handle the result
| Result | What your code should do |
|---|---|
is_terminal:false | Do not treat the verification as complete. Follow next_action and poll within a bounded retry budget. |
status: match | Continue the approved business onboarding flow and store the transaction ID. |
status: review | Pause automation and route the result to a human reviewer. |
status: nomatch | Stop the onboarding path and present the returned next action. |
- Tasks (
io.modelcontextprotocol/tasks) -kyb_verifyreturns a task handle you poll withtasks/getwhen your client declares the capability; otherwise it returns the samenext_actionlong-poll. Task state is per-instance today, so a not-foundtasks/getmeans fall back to the poll. - Tasks (
io.modelcontextprotocol/tasks) - the long-running tools (kyc_verify,kyb_verify) return a task handle you poll withtasks/getwhen your client declares the capability; otherwise they return the samenext_actionlong-poll. Task state is per-instance today, so a not-foundtasks/getmeans fall back to the poll. - MCP Apps / SEP-1865 (
io.modelcontextprotocol/ui) -render_app_verdictreturns a host-renderedui://verdict card (sandboxed iframe,text/html;profile=mcp-app) with a text fallback for non-Apps clients. Enabled per account (TRULIOO_ENABLE_MCP_APPS).
Result contracts
Tools return structured results an agent can branch on directly - not prose to parse.
kyb_verify (terminal shape)
kyc_verify (shape)
- Errors are results, not exceptions. A failed upstream comes back as a typed result the agent can reason about, not a thrown error that ends the run.
- Circuit breaker per upstream. Each verification surface has its own breaker, so one degraded provider does not take down the others.
- Async is explicit.
is_terminal:falsetells the agent to poll rather than assume completion. A long-running operation returns a continuation to poll; exhausting an approved poll budget requires review rather than an unbounded loop.
Give an agent an identity
Any agent can claim any name. Know Your Agent proves the real organization behind an agent and issues a signed, scoped, revocable credential - the Digital Agent Profile (DAP) - that anyone can verify. It rides in the agent's A2A card, so trust travels with the agent.
- Verify the organization. KYC/KYB + sanctions on the accountable owner behind the agent.
- Register the agent. The agent presents its own Ed25519 key; that key is the identity anchor. A build fingerprint binds the credential to this exact agent.
- Sign a scoped mandate.
kya_issue_mandatemints a short-lived, least-privilege attestation for named scopes (e.g.purchase), signed byidentity.trulioo.com. - Publish it. The attestation attaches to your A2A card under
capabilities.extensions[](urihttps://identity.trulioo.com/a2a/kya/v1) and is anchored in a tamper-evident log.
The KYA extension on an A2A agent card
Scopes are signed, but enforced by the relying party. Trulioo signs and audits the allowed scopes; the party accepting the agent is what actually enforces them. The attestation is a verifiable claim of trust, not an authorization grant on its own.
Why agent trust has layers
"Verified" is not one thing. A DAP asserts a stack of independent facts, and a relying party checks the layers its risk calls for. Knowing the layers tells you exactly what a profile does - and does not - prove.
- Identity anchor. The agent holds its own key. Everything else binds to that key, so the profile is about this agent, not a name it typed.
- Integrity & provenance. A build fingerprint binds the credential to the exact code. Change the code and the fingerprint changes - forcing re-attestation.
- Authenticity of use. A possession proof shows the party presenting the card actually controls the anchor key - not a copied card.
- Origin & accountability. KYC/KYB ties the agent to a real, sanctions-screened organization, and every issuance is anchored in a tamper-evident log.
This matters to your company directly: it is what lets you (or your customers) accept an agent's action with a known, accountable party behind it - and decline or step up when a layer is missing. The full trust model →
Verify an agent (DAP)
Verification is the critical path: a system deciding whether to trust an inbound agent confirms its Digital Agent Profile and attestation before acting. Verify through MCP; the issuer also publishes the two keyless, public primitives so any party can check a profile with no account.
Try it live
Drive the mint-then-verify lifecycle end to end. This simulation runs entirely in your browser - no network calls. Mint on the left; verify the same agent on the right.
1 - Issue a credential
Verify org → register agent → sign mandate → anchor in the log.
- The lifecycle trace streams here - one signed step at a time.
2 - Verify an agent
Against the issuer, not the card. The agent from step 1 lands here.
🔒 Run step 1 first - the agent you mint arrives here to verify.
In an agent (recommended)
Call kya_verify_agent with the agent's card - it validates the signature, fingerprint,
expiry and sanctions, and returns the Verified-by-Trulioo record. Add a requested_action to
check it against the signed scope in the same step. This is the integration path; the KYA verification
logic lives behind MCP, not a public write API.
Verify over MCP
$TOKEN comes from Authentication and
$SID from the initialize handshake. If you only need to check a profile
and not run a verification, the public keyless lookup below needs neither.
Public, keyless lookup (for any verifier)
The issuer publishes two public primitives at https://identity.trulioo.com so a relying
party that isn't running an MCP client can still confirm a profile without an account:
GET /kya/attestation/{dap}- look up an agent's current standing by its Digital Agent Profile (the "anyone can check" path).GET /.well-known/jwks.json- the issuer's signing keys (rotation-aware) to verify an attestation JWS yourself.
What a verifier checks: the JWS signature against the pinned issuer key by
kid (the algorithm is pinned from the resolved key, never read from the token
header - blocks alg:none and alg-confusion); the fingerprint against the
agent's own key + card; the exp (short-lived, re-attested on change);
verified; assurance.trust_tier against your own minimum; and the signed
allowed_scopes. Scopes are signed and auditable but enforced by you, the
relying party.
There is no signed sanctions boolean. Signing a standing
sanctions_clear would assert a check that may not have run, on a payment-adjacent
credential. Screening is an optional provenanced claim carried only when it actually ran, and
a hit or review suspends the credential's standing through its status_reference.
Check standing, not a boolean.
The DAP wire schema (ats-v2)
A Digital Agent Profile is a conformant SD-JWT-VC (typ: dc+sd-jwt) carrying a
vct of https://identity.trulioo.com/vct/agent-profile.1. A passport core is
inline - a KYB-verified operator and a composite assurance grade - while the
identity, mandate, status and behavior objects are referenced and dereferenced independently.
This is the exact record the KYA card flips to; the full JSON Schema is
ats-v2-dap.schema.json (governed by ADR-P-022).
DAP 2.0 presentation (public-discovery profile)
Disclosure integrity. assurance (incl. trust_tier) is always
inline; operator (at tier ≥ 2) and screening.result (when present) are
not holder-omittable - a holder cannot strip a signed sanctions hit or claim tier ≥ 2 while
hiding the operator. Only operator.registration_id, screening.watchlists, and
(pairwise profile only) agent_id/build_id are selectively disclosable.
Two profiles. Public discovery reveals agent_id/build_id
inline (shown above). Pairwise withholds them via SD-JWT selective disclosure and substitutes a
per-relying-party sub alias, so a profile isn't linkable across verifiers. The variant is
chosen by the agent's exposure mode - never a caller flag - so an agent can't be tricked into
over-disclosing.
How the DAP projects onto each rail
One DAP, issued once, is projected into each protocol's native shape - KYA proves who is accountable; the rail carries and authenticates the transaction. The mapping below is what actually travels on each rail and which DAP claim the verifier reads.
| Rail | Where the DAP travels | What the verifier reads |
|---|---|---|
| Google A2A Live |
Inline in the Agent Card under capabilities.extensions[], uri identity.trulioo.com/a2a/kya/v1, as a compact JWS in params.attestation. |
The attestation JWS against the issuer JWKS, then operator + assurance.trust_tier from the verified DAP. |
| Google AP2 Live |
The DAP is the credential - a conformant SD-JWT-VC AP2 already speaks (typ: dc+sd-jwt), presented as the mandate. |
iss = identity.trulioo.com, the cnf holder-key proof, and the inline operator/assurance core. |
| Google + Shopify UCP Live |
Referenced from the merchant profile the business publishes with its signing keys. | operator.kyb = verified and assurance.trust_tier - is this a real, screened business? |
| OpenAI + Stripe ACP Live |
Checked out-of-band before the delegated Stripe token is honored, via kya_verify_agent(card). |
The signed capabilities scope (e.g. checkout) and operator - is this agent allowed to make this purchase? |
| Visa TAP Preview |
TAP signs the request (RFC 9421, Ed25519) with the agent key; the DAP is resolved from that key. | The cnf.jkt thumbprint maps the signing key to a DAP, then operator - the accountable org behind the key. |
| Mastercard Agent Pay Preview |
The Agentic Token binds to the DAP's durable agent_id + verified operator. |
agent_id and operator - the tokenized card is bound to a real, verified organization. |
| Cloudflare Web Bot Auth Live |
Signed edge requests (RFC 9421) carry Signature-Agent; the DAP sits beneath the signing key. |
cnf key match + operator/assurance - replaces a spoofable User-Agent with a verified org. |
| Coinbase x402 Live |
The wallet signs the on-chain payment; the DAP rides the bridged A2A card alongside it. | The DAP attestation - the wallet moves value, the DAP proves the accountable org behind the agent. |
| Skyfire Live |
Skyfire's identity token references the DAP as its regulated assurance source. | assurance.trust_tier (e.g. trulioo:tier-2) - the KYC/KYB depth the token anchors to. |
Across every rail the DAP's role is the same - prove the accountable organization and its signed scope; the rail enforces and settles. No proprietary token, no lock-in: it's a conformant SD-JWT-VC anyone can verify against the issuer JWKS.
Drop-in "Verified" badge
Prefer not to build the UI? Embed the same <trulioo-verified> element Trulioo runs on
its own surfaces. It runs the live attestation lookup itself, stays hidden until the agent verifies, and
opens the full Digital Agent Profile on click - Organization, Issuer, DAP, verified-as-of, sanctions,
attestations, scopes, and a link into the transparency log. One framework-agnostic custom element; no build
step. It's live in the hero of the sibling Know Your Agent page.
Embed it
Orchestration patterns
The tools are typed and composable, so an agent chains them mid-task and branches on each result. The examples below show how to combine the raw tools.
Pattern 1 - Verify a person before a high-risk action
The agent checks identity mid-conversation and branches on the typed status.
Ships as /trulioo-mcp:kyc-onboarding.
KYB due diligence - discover, verify, screen
Pattern 2 - Onboard a business, then screen it
Find the business, confirm the correct candidate, verify it, and branch on the typed result.
Pattern 3 - Give the agent its own identity (KYA)
Once the org behind the agent is verified, mint the agent's DAP so every downstream call is attributable.
Keep the business identity continuous. Carry the selected registration identifier from search into verification, store the returned transaction ID, and use that transaction as the anchor for report retrieval.
Enterprise agent teams. A fleet shares one MCP connection and one identity layer - every agent inherits the same verification tools, and each carries its own DAP, so downstream systems know which agent (and which accountable org) took an action. One integration, governed centrally.
Security & honest limits
- Schema-enforced inputs. Every tool validates its arguments (
additionalProperties: false), so malformed or injected calls are rejected before reaching an upstream. - Prompt-injection resistance. Tools act only on their typed arguments; free-text in a document or field is data, never an instruction to the server.
- Algorithm pinning. Attestation verification pins the algorithm from the resolved key (EdDSA / ES256 only) -
alg:noneand alg-confusion attacks are rejected. - Honest limits. A DAP proves identity, integrity, scope and accountability - it does not authorize a payment or guarantee behavior. Scope enforcement is the relying party's; certified biometric liveness has a defined boundary. We surface dependencies we do not own.
- Governed surface. The verification agents and skills behind these tools are eval-gated and release-controlled - the same discipline you would apply to a compliance-critical dependency.
FAQ
Should I search before calling kyb_verify?
Search when you do not already have an authoritative registration identifier. If search returns
multiple candidates, confirm the correct business with kyb_disambiguate_candidate
before verification.
What should I do when search returns several businesses?
Do not guess. Use kyb_disambiguate_candidate and ask the user to confirm the correct
business before you call kyb_verify.
How do I continue after KYB completes?
Use the transaction ID to retrieve and store the completed report.
Does an agent need its own key for KYA?
Yes. The agent's own key is the identity anchor; the profile binds to it. Trulioo does not mint the agent's key for it.
Does the attestation authorize a payment?
No. It is a signed, verifiable claim of identity and scope. Whether to accept an action is the relying party's decision; scope is enforced there.
How does someone verify an agent without a key?
The issuer publishes its signing keys at /.well-known/jwks.json; verification is a public signature check against those keys.