BCP

Ultron as consumer

Every Ultron agent that mentions, researches, or transacts with another company should fetch that company's BCP manifest first. Bi-directional adoption is the property that makes BCP useful from day one - Ultron is both the largest publisher and the largest consumer of manifests in our own product.

Updated today

Why Ultron reads manifests

The consumer side closes the loop.

Publishing manifests is half the story. If no one reads them, they decay into the same fate as agents.txt - published in marketing copy, ignored in practice. Ultron reads every manifest it can find, automatically. Three places matter:

Where Ultron reads a manifestWhat it unlocks
User mentions a domain in chatThe agent looks up the manifest, learns the company's MCP endpoint, treats the company as a first-class actor for the rest of the conversation.
A lead enrichment touches a domainIdentity block fills in legalName, jurisdiction, LEI without an extra Apollo / Crunchbase call. Free signal.
A scheduled agent or background mission targets a companyThe mission planner reads the target's manifest to pick the right endpoint per step (catalog query vs lead submit vs booking).
Note
Reading a manifest does not cost credits. It is a free enrichment that happens before any model token is spent on the company in question. Once an Ultron agent has read a manifest, every downstream action against that company is targeted and verified.

The bcp_lookup chat tool

A native chat v2 tool that wraps the resolution algorithm.

src/lib/tools/providers/bcp.tsts
1export const BCP_TOOLS: ToolDef[] = [
2 {
3 name: "bcp_lookup",
4 description:
5 "Resolve a company's Business Context Protocol manifest by " +
6 "domain. Returns identity, capabilities, commerce primitives, " +
7 "policy, and current state. Use this before transacting with " +
8 "or referring to a company by name.",
9 input_schema: {
10 type: "object",
11 properties: {
12 domain: { type: "string", description: "Bare host, e.g. acme.com." },
13 verify: { type: "boolean", default: true, description: "Run signature + DNS verification." },
14 scopes: {
15 type: "array",
16 items: { type: "string" },
17 description: "If provided, narrow the returned MCP servers to ones supporting these scopes.",
18 },
19 },
20 required: ["domain"],
21 },
22 },
23]

Implicit invocation

The chat-v2 system prompt instructs the model to callbcp_lookup the first time a new domain enters the conversation, before invoking any other tool that touches that domain. The result is cached for the conversation lifetime; subsequent mentions reuse the cache.

Resolution algorithm

What runs when bcp_lookup is called.

  1. 01
    Normalise
    Reduce the input to an apex domain. https://www.acme.com/productsacme.com.
  2. 02
    Race apex vs www
    HTTPS GET against https://acme.com/.well-known/business.json and https://www.acme.com/.well-known/business.json in parallel with a 5s budget. First 2xx wins.
  3. 03
    Fall back to registry
    If both 404 or time out, call https://bcp.51ultron.com/lookup?domain=acme.com. Returns either the Ultron-hosted manifest URL or 404.
  4. 04
    Validate schema
    Parse JSON-LD. Reject if @type does not include BusinessCard or identity.domain does not match the resolved host.
  5. 05
    Verify signature (if present)
    Run the verification flow from the /docs/bcp/signing page. Compute the trust level (L0-L3).
  6. 06
    Cache and return
    Store with the source URL, hash, and trust level. Return a structured response to the model.

Verification level

The four levels and what each unlocks.

LevelMeansWhat Ultron will do with it
L0 - AdvisoryNo signature, or signature fails. Manifest content not authenticated.Use identity for display. Show endpoints in UI but warn before submitting. Never auto-act on write scopes.
L1 - IdentifiedSigned, signing key in identity.publicKey, no DNS binding.Same as L0 for write actions. Use identity for narrative grounding.
L2 - DNS-pinnedSigned, signing key matches _bcp.<domain> TXT.Auto-act on read scopes. Surface confirmation prompts before write scopes. Default tier for SMB customers.
L3 - vLEI-boundSigned by a vLEI role credential, chained to GLEIF.Auto-act on configured write scopes within rate limits. Acceptable counterparty for AP2 mandates.
Warning
Trust-level escalation must be explicit in user policy. By default, Ultron does not auto-act on write scopes even at L3. The workspace owner opts in per scope, per counterparty, or per agent.

Caching strategy

Honour the publisher's cache headers, with a floor.

At a glance
Default TTL
Honour Cache-Control: max-age. Floor at 60 seconds, cap at 24 hours.
Stale-while-revalidate
If the manifest is stale, return cached, refresh in background.
ETag revalidation
On expiry, conditional GET with If-None-Match. 304 skips parse + verify.
Conversation cache
Per chat session, cache for the entire session regardless of TTL. Single domain mention triggers one fetch only.
Tenant cache
Cross-conversation cache keyed by (tenant_id, domain). Postgres-backed. Avoids redundant fetches inside one workspace.
Global cache
None. Each tenant fetches independently. Privacy reason: who is asking about whom should not be cross-tenant observable.

Acting on a manifest

From a verified manifest to a tool call.

  1. 01
    Pick the right MCP server
    If the model needs a write scope, filter mcpServers by scope match. If multiple servers match, prefer the one with the strongest auth (oauth2 > bearer > apikey > none).
  2. 02
    Connect
    If oauth2, run the connect-once flow (per workspace, per counterparty domain). Cache the access token. If bearer, prompt the user for the token once. If none, connect anonymously.
  3. 03
    Issue the tool call
    Standard MCP tool invocation. The manifest's scope claim should match what the server actually exposes, but always re-check by querying the server's tool list before calling.
  4. 04
    Record the action
    Every call against a BCP-resolved server is written to bcp_call_log with the manifest hash, the scope used, and the response code. Used for billing, abuse detection, and audit.
  5. 05
    Handle policy violations
    If the server rejects the call as out-of-scope, surface the diff between the manifest's claim and the server's actual behaviour. This is a publisher bug; flag it for the customer.

Error handling

What Ultron does when a manifest is missing, broken, or hostile.

ErrorBehaviour
No manifest publishedTreat the domain as opaque. Use traditional research tools (web search, scrape) instead. No BCP-driven actions.
Manifest unreachable (DNS, timeout, 5xx)One retry with backoff. Then fall back as if no manifest published. Log for the operator dashboard.
Manifest is malformed JSONReject, log, surface to publisher via support@ if the workspace has Ultron-issued contact.
Signature does not verifyDowngrade to L0. Continue to use identity block for narrative but never auto-act.
Manifest claims a domain that does not match the hostReject outright. This is a strong impersonation signal.
Manifest is much larger than 256 KiBReject. Treat as malformed.
bcp:expires in the pastOne re-fetch (the cache may be stale). If still expired, downgrade to L1 maximum.
Signing key revoked (vLEI witness mesh)Reject manifest. Surface a security event. Do not auto-act.

Safety considerations

What an attacker could do, and how the protocol pushes back.

A manifest can lie
A manifest is a self-description. Even when signed, the publisher chose what to put in it. policy.allowActionsmay list scopes the publisher does not actually honour. The MCP server pointed at may rate-limit or reject. The incident webhook may never fire. Always treat the manifest as a hint, never as enforcement.
AttackDefense in BCP
Impersonation: attacker hosts manifest claiming to be acme.comSignature must verify against acme.com's DNS-pinned key. Without that, only L0 (advisory) trust.
Phishing: attacker registers acme.co (typo) and publishes legit-looking manifestTrust level is per-domain. The user must approve cross-counterparty actions. Ultron surfaces the resolved domain in confirmation prompts.
Replay: serve an old manifest where allowActions was broaderbcp:expires + signedAt freshness check. Stale manifests cannot authorise write scopes.
Confused deputy: A's manifest tricks Ultron into acting against BManifests are scoped to the domain they live on. Cross-domain actions require the target domain's manifest, fetched separately.
Resource exhaustion: huge manifest, infinite-redirect loopSize cap 256 KiB. Redirect cap 3. Timeout 5s. Hard limits, no negotiation.
Sensitive data leak: manifest reveals private endpointsPublisher's responsibility. Ultron only generates manifest fields from data the customer marked as public on /company-demo.