Apigee Agent Onboarding
Apigee Agent Onboarding — automated agent self-registration on Google Apigee API Management. Verifies Web Bot Auth signatures (RFC 9421), composes developer + developer-app + app-key operations into a single scoped credential issuance, and emits an audit event to Google Cloud Audit Logs (the canonical Tier 2 multi-origin case). Companion to the API Evangelist agent-onboarding pattern. 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
Register an agent with the Apigee-backed surface and obtain consumerKey + consumerSecret scoped to one API Product.
agent-revoke
Revoke an issued agent credential.
Capability Spec
naftiko: 1.0.0-alpha2
info:
label: Apigee Agent Onboarding
description: 'Apigee Agent Onboarding — automated agent self-registration on Google Apigee API
Management. Verifies Web Bot Auth signatures (RFC 9421), composes developer + developer-app +
app-key operations into a single scoped credential issuance, and emits an audit event to
Google Cloud Audit Logs (the canonical Tier 2 multi-origin case). Companion to the API
Evangelist agent-onboarding pattern. 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:
- Apigee
- Google Cloud
- Agent Onboarding
- Web Bot Auth
- RFC 9421
- API Products
- Cloud Audit Logs
- 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/apigee
binds:
- namespace: env
keys:
APIGEE_ORG: APIGEE_ORG
APIGEE_ACCESS_TOKEN: APIGEE_ACCESS_TOKEN
GCP_PROJECT_ID: GCP_PROJECT_ID
CLOUD_AUDIT_LOG_NAME: CLOUD_AUDIT_LOG_NAME
AGENT_TRUSTED_ISSUERS: AGENT_TRUSTED_ISSUERS
AGENT_CONSENT_HASH: AGENT_CONSENT_HASH
capability:
consumes:
- type: http
namespace: apigee-management
baseUri: https://apigee.googleapis.com/v1
description: Apigee Management API operations for developer + app + key + product composition.
resources:
- name: org-developers
path: /organizations/{organizationId}/developers
operations:
- name: createdeveloper
method: POST
description: Create a developer record representing the agent's operator identity.
outputRawFormat: json
outputParameters:
- { name: result, type: object, value: $. }
inputParameters:
- { name: organizationId, in: path, type: string, required: true }
- { name: body, in: body, type: object, required: true }
- name: org-developer-apps
path: /organizations/{organizationId}/developers/{developerEmail}/apps
operations:
- name: createapp
method: POST
description: Create the agent's developer-app. Returns consumerKey + consumerSecret
(the credential) as part of the response.
outputRawFormat: json
outputParameters:
- { name: result, type: object, value: $. }
inputParameters:
- { name: organizationId, in: path, type: string, required: true }
- { name: developerEmail, in: path, type: string, required: true }
- { name: body, in: body, type: object, required: true }
- name: org-developer-app-keys
path: /organizations/{organizationId}/developers/{developerEmail}/apps/{appName}/keys/{consumerKey}
operations:
- name: deleteappkey
method: DELETE
description: Revoke a previously-issued app key (the credential).
outputRawFormat: json
outputParameters:
- { name: result, type: object, value: $. }
- name: org-apiproducts
path: /organizations/{organizationId}/apiproducts
operations:
- name: listapiproducts
method: GET
description: List existing API Products (used to resolve scope names to Product IDs).
outputRawFormat: json
outputParameters:
- { name: result, type: object, value: $. }
- name: createapiproduct
method: POST
description: Create an API Product if the scope-tier Product doesn't already exist.
The Product carries the quota, the rate limit, and which API operations are accessible.
outputRawFormat: json
outputParameters:
- { name: result, type: object, value: $. }
authentication:
type: bearer
token: '{{env.APIGEE_ACCESS_TOKEN}}'
- type: http
namespace: gcp-cloud-audit-logs
baseUri: https://logging.googleapis.com/v2
description: Cloud Audit Logs — Apigee push audit out-of-band here. The worker queries
this surface for the apigee.googleapis.com createDeveloper + createDeveloperApp events
and joins with the structured custom audit event written here by the orchestration.
resources:
- name: entries-write
path: /entries:write
operations:
- name: writelogentries
method: POST
description: Write a structured agent-onboarding audit event.
outputRawFormat: json
outputParameters:
- { name: result, type: object, value: $. }
inputParameters:
- { name: body, in: body, type: object, required: true }
authentication:
type: bearer
token: '{{env.APIGEE_ACCESS_TOKEN}}'
orchestration:
- name: onboard-agent
description: End-to-end onboarding — verify identity, classify scopes, ensure scope-tier
API Product, create developer + app, capture consumerKey, emit Cloud Audit Logs event.
inputs:
- { name: signature, type: object, required: true }
- { name: signature_agent, type: string, required: true }
- { name: skill_id, type: string, required: true }
- { name: requested_scopes, type: array, required: true }
- { 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: classify_scopes
type: builtin.policy.scope-classify
with:
requested: '${input.requested_scopes}'
- id: ensure_api_product
type: builtin.upsert
description: Resolve scope name to an API Product; create if missing.
with:
list_call: apigee-management.listapiproducts
filter: 'name == "${steps.classify_scopes.target}"'
create_call: apigee-management.createapiproduct
create_with:
organizationId: '{{env.APIGEE_ORG}}'
body:
name: '${steps.classify_scopes.target}'
displayName: 'Agent-onboarded scope tier'
approvalType: auto
- id: create_developer
call: apigee-management.createdeveloper
with:
organizationId: '{{env.APIGEE_ORG}}'
body:
email: 'agent-${steps.verify_signature.agent_id}@${input.contact.operator}'
firstName: Agent
lastName: '${steps.verify_signature.agent_id}'
userName: 'agent-${steps.verify_signature.agent_id}'
attributes:
- { name: operator, value: '${input.contact.operator}' }
- { name: skill_id, value: '${input.skill_id}' }
- id: create_app
call: apigee-management.createapp
description: Create the developer-app with the scope-tier Product attached. The
response contains the credentials envelope including consumerKey + consumerSecret.
with:
organizationId: '{{env.APIGEE_ORG}}'
developerEmail: '${steps.create_developer.email}'
body:
name: 'agent-app-${steps.verify_signature.agent_id}'
apiProducts:
- '${steps.ensure_api_product.name}'
attributes:
- { name: operator, value: '${input.contact.operator}' }
- id: emit_audit
call: gcp-cloud-audit-logs.writelogentries
with:
body:
entries:
- logName: '{{env.CLOUD_AUDIT_LOG_NAME}}'
resource:
type: apigee_api
labels:
project_id: '{{env.GCP_PROJECT_ID}}'
org: '{{env.APIGEE_ORG}}'
jsonPayload:
event_type: agent.onboarded
agent_id: '${steps.verify_signature.agent_id}'
operator: '${input.contact.operator}'
support_url: '${input.contact.support_url}'
skill_id: '${input.skill_id}'
scope_tier: '${steps.classify_scopes.target}'
consent_hash: '${input.consent_hash}'
app_name: '${steps.create_app.name}'
consumer_key_prefix: '${steps.create_app.credentials[0].consumerKey.slice(0,8)}'
output:
agent_id: '${steps.verify_signature.agent_id}'
developer_email: '${steps.create_developer.email}'
app_name: '${steps.create_app.name}'
credential:
type: OAuth2-ClientCredentials
consumer_key: '${steps.create_app.credentials[0].consumerKey}'
consumer_secret: '${steps.create_app.credentials[0].consumerSecret}'
revocation_url: '/v1/agents/${steps.verify_signature.agent_id}/revoke'
scope_tier: '${steps.classify_scopes.target}'
- name: revoke-agent
description: Revoke the consumerKey by deleting the app key entry.
inputs:
- { name: agent_id, type: string, required: true }
- { name: developer_email, type: string, required: true }
- { name: app_name, type: string, required: true }
- { name: consumer_key, type: string, required: true }
steps:
- id: delete_key
call: apigee-management.deleteappkey
with:
organizationId: '{{env.APIGEE_ORG}}'
developerEmail: '${input.developer_email}'
appName: '${input.app_name}'
consumerKey: '${input.consumer_key}'
output:
revoked: true
exposes:
- type: rest
namespace: apigee-agent-onboarding-rest
port: 8080
description: REST surface — /v1/agents/onboard for Apigee-backed providers.
resources:
- path: /v1/agents/onboard
name: agents-onboard
operations:
- method: POST
name: onboardagent
call: orchestration.onboard-agent
with:
signature: rest.headers.signature
signature_agent: rest.headers.signature-agent
skill_id: rest.body.skill_id
requested_scopes: rest.body.scopes
consent_hash: rest.body.consent_hash
contact: rest.body.contact
- path: /v1/agents/{agent_id}/revoke
name: agents-revoke
operations:
- method: POST
name: revokeagent
call: orchestration.revoke-agent
- type: mcp
namespace: apigee-agent-onboarding-mcp
port: 9090
transport: http
description: MCP surface — agent-register and agent-revoke tools.
tools:
- name: agent-register
description: Register an agent with the Apigee-backed surface and obtain
consumerKey + consumerSecret scoped to one API Product.
hints: { readOnly: false, destructive: false, idempotent: false }
call: orchestration.onboard-agent
- name: agent-revoke
description: Revoke an issued agent credential.
hints: { readOnly: false, destructive: true, idempotent: true }
call: orchestration.revoke-agent
- type: agent-skill
namespace: apigee-agent-onboarding-skill
description: 'Agent skill at /skills/onboard-agent.md. Apigee credentials are
two-part (consumerKey + consumerSecret), typically used as OAuth2 client credentials;
the skill documents the client_credentials grant flow against the provider OAuth endpoint.'
skill:
name: onboard-agent
file: skills/onboard-agent.md