Skip to content

Attaching AgenID Identity to a Bland AI Agent

Status: integration pattern, not a shipped package. There is no @agenid/adapter-bland today. This document shows how to wire agenid:<ULID> identity and Ed25519 proof verification into a Bland AI phone agent using Bland's existing, documented APIs plus @agenid/core. It is written for engineers integrating the two platforms themselves; nothing described here implies AgenID has a first-party Bland package.

Field names below (metadata, request_data, Custom Tools, X-Webhook-Signature) are Bland's own, as documented at docs.bland.ai. Verify against Bland's current docs before shipping — API surfaces change.

Why attach an identity at all

Bland is used for enterprise telephony at scale — outbound and inbound calling on behalf of an organization. Nothing in a raw Bland call or agent config gives a call recipient, or another agent, a permanent, independently checkable identity to point to. agenid:<ULID> fills that gap; an AgenID manifest and its Ed25519 proof let a third party check that identity claim offline, without trusting Bland's or AgenID's database.

Where identity fits in Bland's model

Bland's Send Call (POST /v1/calls) request accepts a metadata field (arbitrary JSON object, opaque to Bland) and a request_data field (values available for {{variable}} templating into prompts and tool calls). That is the natural place to carry an agenid:<ULID>:

{
  "phone_number": "+15555550100",
  "metadata": {
    "agenid": "agenid:01J8Z3K3F2QZ9X6V7R4T8N2W5Y"
  }
}

As with the other voice platforms, this does not make Bland verify anything on its own — it makes the identifier travel with the call record and, via request_data, available for templating into prompts and tool calls.

Verifying the identity at call time

Use a Bland Custom Tool — a tool definition with name, url, method, headers, body (templated from LLM-extracted conversation values via {{input.property}}), and a response map that extracts fields (via JSONPath) back into the conversation as {{variable_name}} — that resolves the agent's agenid:<ULID> against https://agenid.com/a/<ulid> and folds the verification level back into the call. Bland's optional speech field lets the agent talk while awaiting the response, so a verification lookup doesn't need to create dead air. @agenid/core supplies the Ed25519 + RFC 8785 verification primitives; the HTTP fetch and tool wiring are yours to write — no SDK glue exists for this yet.

Verifying webhook authenticity

Bland signs its webhooks (including post-call webhooks) with an X-Webhook-Signature header — an HMAC-SHA256 hex digest computed over the raw request body using your signing secret (see Webhook Signing). Verifying that header authenticates the payload as coming from Bland — it is a separate concern from AgenID's proof, which authenticates a claim about the *agent's identity*. Both checks matter and neither substitutes for the other:

  • X-Webhook-Signature → "this event really came from Bland."
  • AgenID manifest proof → "this specific agent's identity claim was really signed by its declared operator (and, if verified, checked by an independent authority)."

What's not built yet

  • No @agenid/adapter-bland package. If one gets built, it would wrap the Custom Tool pattern above, not replace it.
  • No confirmed schema for Bland's metadata field beyond "accepts an arbitrary JSON object" — treat the example above as illustrative, not normative.
  • Regulatory framing for any AI-disclosure requirement in this flow should cite EU AI Act Article 50, not any California disclosure statute — see the AgenID spec's own disclosure guidance.

References