Deutsche Telekom / CAMARA Agent Onboarding (Carrier-Grade)
Deutsche Telekom + CAMARA Agent Onboarding — carrier-grade pattern. Differs fundamentally from SaaS-gateway adapters because telecom-network APIs require legal-entity operator attestation, per-API-call user consent flows, regulatory audit retention, and rate limits measured in carrier-network terms. Three-layer trust model: operator (carrier knows who is calling), agent (Web Bot Auth identifies the specific agent), call (end-user authorizes this specific lookup). Runtime policy enforcement (signature verify, consent check, scope classify, audit emit) lives in the orchestration.steps below — each step that gates issuance carries on_failure: deny. Lint-time validation of this capability shape lives in the companion Polychro ruleset at https://github.com/api-evangelist/posts/blob/main/polychro/agent-onboarding-rules.yaml — Polychro is Naftiko's governance layer, separate from the capability spec, and is the correct home for cross-object consistency rules that apply across every agent-onboarding capability.
What You Can Do
MCP Tools
agent-register
agent-revoke
Capability Spec
naftiko: 1.0.0-alpha2
info:
label: Deutsche Telekom / CAMARA Agent Onboarding (Carrier-Grade)
description: 'Deutsche Telekom + CAMARA Agent Onboarding — carrier-grade pattern. Differs
fundamentally from SaaS-gateway adapters because telecom-network APIs require legal-entity
operator attestation, per-API-call user consent flows, regulatory audit retention, and
rate limits measured in carrier-network terms. Three-layer trust model: operator (carrier
knows who is calling), agent (Web Bot Auth identifies the specific agent), call (end-user
authorizes this specific lookup). Runtime policy enforcement (signature verify, consent check, scope classify, audit emit) lives in the orchestration.steps below — each step that gates issuance carries on_failure: deny. Lint-time validation of this capability shape lives in the companion Polychro ruleset at https://github.com/api-evangelist/posts/blob/main/polychro/agent-onboarding-rules.yaml — Polychro is Naftiko''s governance layer, separate from the capability spec, and is the correct home for cross-object consistency rules that apply across every agent-onboarding capability.'
tags:
- Deutsche Telekom
- CAMARA
- Open Gateway
- Telco Network APIs
- Agent Onboarding
- Carrier-Grade
- Per-Call Consent
- Regulatory Audit
- Naftiko Capability
created: '2026-05-28'
modified: '2026-05-28'
related:
- https://apievangelist.com/2026/05/27/automated-agent-onboarding-is-a-naftiko-capability-not-a-gateway-feature/
- https://github.com/api-evangelist/deutsche-telekom
- https://github.com/api-evangelist/camara-project
binds:
- namespace: env
keys:
DT_PORTAL_BASE_URI: DT_PORTAL_BASE_URI
DT_OPERATOR_TOKEN: DT_OPERATOR_TOKEN
DT_OPERATOR_AGREEMENT_ID: DT_OPERATOR_AGREEMENT_ID
REGULATORY_AUDIT_BUCKET: REGULATORY_AUDIT_BUCKET
REGULATORY_AUDIT_RETENTION_YEARS: REGULATORY_AUDIT_RETENTION_YEARS
AGENT_TRUSTED_ISSUERS: AGENT_TRUSTED_ISSUERS
AGENT_CONSENT_HASH: AGENT_CONSENT_HASH
capability:
consumes:
- type: http
namespace: dt-developer-portal
baseUri: '{{env.DT_PORTAL_BASE_URI}}'
description: DT developer portal — agent registration under an existing operator
agreement, per-API subscription, and per-call consent flow initiation.
resources:
- name: operator-agents
path: /developer-portal/operators/{opId}/agents
operations:
- name: registeragent
method: POST
description: Register an agent under the operator's pre-existing master agreement.
Returns agent_id + client credentials. Operator agreement is a separate one-time
legal flow that establishes the trust anchor.
outputRawFormat: json
outputParameters:
- { name: result, type: object, value: $. }
inputParameters:
- { name: opId, in: path, type: string, required: true }
- { name: body, in: body, type: object, required: true }
- name: deleteagent
method: DELETE
description: Revoke agent registration.
outputRawFormat: json
outputParameters:
- { name: result, type: object, value: $. }
- name: agent-subscriptions
path: /developer-portal/agents/{agentId}/subscriptions
operations:
- name: createsubscription
method: POST
description: Subscribe the agent to a specific CAMARA API. Each subscription is
scope-tier-bound (which APIs, what call volume, what categories of subscriber
data the agent may query).
outputRawFormat: json
outputParameters:
- { name: result, type: object, value: $. }
inputParameters:
- { name: agentId, in: path, type: string, required: true }
- { name: body, in: body, type: object, required: true }
- name: consent-flows
path: /consent-flows/{flowType}
operations:
- name: getconsentflow
method: GET
description: Retrieve the consent-flow definition for a CAMARA API (number
verification, location, SIM swap, etc.). Many flows are three-legged OAuth
requiring per-end-user authorization at call time.
outputRawFormat: json
outputParameters:
- { name: result, type: object, value: $. }
- name: consent-sessions
path: /consent-flows/{flowType}/sessions
operations:
- name: initiateconsentsession
method: POST
description: Initiate a per-end-user consent session at call time — distinct
from the agent-onboarding flow but invoked from the same capability surface.
outputRawFormat: json
outputParameters:
- { name: result, type: object, value: $. }
authentication:
type: bearer
token: '{{env.DT_OPERATOR_TOKEN}}'
- type: http
namespace: regulatory-archive
baseUri: https://archive.{{env.DT_PORTAL_BASE_URI}}
description: Regulatory audit archive — separate from observability streams.
Long-retention immutable storage for legal record-keeping (typically 7-10 years).
resources:
- name: events
path: /events
operations:
- name: writeevent
method: POST
description: Write a regulatory audit record with retention controls.
outputRawFormat: json
outputParameters:
- { name: result, type: object, value: $. }
inputParameters:
- { name: body, in: body, type: object, required: true }
authentication:
type: bearer
token: '{{env.DT_OPERATOR_TOKEN}}'
orchestration:
- name: onboard-agent
description: Phase 2 onboarding — assumes Phase 1 (operator master agreement) is
already complete. Verifies Web Bot Auth, registers agent under operator, subscribes
to requested CAMARA APIs, emits to both observability and regulatory archive streams.
Phase 3 (per-API call consent) is initiated at runtime via the same capability's
initiateconsentsession surface.
inputs:
- { name: signature, type: object, required: true }
- { name: signature_agent, type: string, required: true }
- { name: operator_id, type: string, required: true, description: 'Operator must hold an active master agreement with the carrier — Phase 1.' }
- { name: skill_id, type: string, required: true }
- { name: requested_apis, type: array, required: true, description: 'CAMARA APIs the agent will call (number-verification, device-location, sim-swap, etc.).' }
- { name: consent_hash, type: string, required: true }
- { name: contact, type: object, required: true }
steps:
- id: verify_signature
type: builtin.web-bot-auth.verify
with:
signature: '${input.signature}'
agent: '${input.signature_agent}'
trusted_issuers: '{{env.AGENT_TRUSTED_ISSUERS}}'
on_failure: deny
- id: verify_consent
type: builtin.policy.assert
with:
assert: '${input.consent_hash} == {{env.AGENT_CONSENT_HASH}}'
on_failure: deny
- id: verify_operator_agreement
type: builtin.policy.assert
description: Confirm the operator's master agreement is active and current.
with:
assert: '${input.operator_id} == {{env.DT_OPERATOR_AGREEMENT_ID}}'
on_failure: deny
- id: classify_apis
type: builtin.policy.scope-classify
description: Map requested CAMARA APIs against the operator's agreement-permitted
API list. Apis outside the agreement are deny.
with:
requested: '${input.requested_apis}'
- id: register_agent
call: dt-developer-portal.registeragent
with:
opId: '${input.operator_id}'
body:
name: 'agent-${steps.verify_signature.agent_id}'
operator_email: '${input.contact.operator}'
support_url: '${input.contact.support_url}'
purpose: '${input.contact.purpose}'
skill_id: '${input.skill_id}'
- id: subscribe_apis
type: builtin.for-each
description: One subscription per requested CAMARA API.
with:
items: '${steps.classify_apis.auto}'
do:
- id: subscribe
call: dt-developer-portal.createsubscription
with:
agentId: '${steps.register_agent.agent_id}'
body:
api: '${item.api}'
rate_limit_subscribers_per_day: '${item.subscribers_per_day_cap}'
consent_flow_type: '${item.consent_flow}'
- id: emit_observability_audit
type: builtin.audit.emit
description: Operational observability stream for monitoring and incident response.
with:
target: dt-developer-portal.agent-subscriptions
custom_event:
event_type: agent.onboarded
agent_id: '${steps.verify_signature.agent_id}'
operator_id: '${input.operator_id}'
apis: '${steps.classify_apis.auto}'
- id: emit_regulatory_audit
call: regulatory-archive.writeevent
description: Regulatory archive — separate immutable stream with long retention.
This is the record national regulators will inspect.
with:
body:
event_type: agent.registered
regulator_inspectable: true
retention_years: '{{env.REGULATORY_AUDIT_RETENTION_YEARS}}'
agent_id: '${steps.verify_signature.agent_id}'
operator_id: '${input.operator_id}'
contact: '${input.contact}'
apis: '${steps.classify_apis.auto}'
consent_hash: '${input.consent_hash}'
signature_keyid: '${steps.verify_signature.keyid}'
signature_alg: '${steps.verify_signature.alg}'
timestamp: '${now.iso}'
output:
agent_id: '${steps.verify_signature.agent_id}'
operator_id: '${input.operator_id}'
subscription_ids: '${steps.subscribe_apis.results}'
credential:
type: OAuth2-ClientCredentials
client_id: '${steps.register_agent.client_id}'
client_secret: '${steps.register_agent.client_secret}'
revocation_url: '/v1/agents/${steps.verify_signature.agent_id}/revoke'
per_call_consent_required: '${steps.classify_apis.auto[*].consent_flow}'
regulatory_audit_id: '${steps.emit_regulatory_audit.id}'
- name: revoke-agent
description: Revoke agent registration; subscriptions cascade.
inputs:
- { name: operator_id, type: string, required: true }
- { name: agent_id, type: string, required: true }
steps:
- id: delete_agent
call: dt-developer-portal.deleteagent
with:
opId: '${input.operator_id}'
agentId: '${input.agent_id}'
- id: emit_revoke_audit
call: regulatory-archive.writeevent
with:
body:
event_type: agent.revoked
agent_id: '${input.agent_id}'
operator_id: '${input.operator_id}'
timestamp: '${now.iso}'
output:
revoked: true
exposes:
- type: rest
namespace: dt-camara-agent-onboarding-rest
port: 8080
resources:
- path: /v1/agents/onboard
operations:
- { method: POST, name: onboardagent, call: orchestration.onboard-agent }
- path: /v1/agents/{agent_id}/revoke
operations:
- { method: POST, name: revokeagent, call: orchestration.revoke-agent }
- type: mcp
namespace: dt-camara-agent-onboarding-mcp
port: 9090
transport: http
tools:
- name: agent-register
hints: { readOnly: false, destructive: false, idempotent: false }
call: orchestration.onboard-agent
- name: agent-revoke
hints: { readOnly: false, destructive: true, idempotent: true }
call: orchestration.revoke-agent
- type: agent-skill
namespace: dt-camara-agent-onboarding-skill
description: 'Agent skill at /skills/onboard-agent.md. CAMARA-specific addendum:
Phase 1 (operator master agreement) is one-time and requires human + legal involvement;
only Phase 2 (per-agent registration) is automated by this capability. Per-call consent
(Phase 3) is the agent''s responsibility at runtime per the consent-flow definition
returned for each subscribed API.'
skill:
name: onboard-agent
file: skills/onboard-agent.md