Deutsche Telekom · Capability

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.

Run with Naftiko Deutsche TelekomCAMARAOpen GatewayTelco Network APIsAgent OnboardingCarrier-GradePer-Call ConsentRegulatory AuditNaftiko Capability

What You Can Do

POST
Onboardagent
/v1/agents/onboard
POST
Revokeagent
/v1/agents/{agent_id}/revoke

MCP Tools

agent-register

agent-revoke

idempotent

Capability Spec

dt-camara-agent-onboarding.yaml Raw ↑
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