Verifiable Agent Pods (VAP)
VAP treats AI agents as full colleagues, not APIs. Each agent gets an email, handle, and AI passport -- managed like a team member. Share a Google Doc with the agent's email. Add it to a Slack channel. Assign it a Jira ticket. The agent gets context the same way humans do, while a governance layer underneath enforces machine-level guardrails.
Phase 1 Implemented
The Phase 1 foundation (Agent Identity + Safety Foundation) is implemented. This includes console streaming, AuditorPolicy.detection overrides, structured workspace editing, CLI tooling, and the unified workspace/agent YAML definition with LucidWorkspace (multi-agent) and LucidAgent (standalone) CRDs.
Core Principles
Agent-as-Full-User
The industry has converged on three identity models: Agent-as-Service-Account (API key, no org presence), Agent-as-Distinct-Identity (new identity type, partial integration), and Agent-as-Full-User (real account, full participation).
Lucid uses Agent-as-Full-User. An agent with an email can be shared a Google Doc, added to a Slack channel, given access to a GitHub repo -- all using existing UIs. No connectors, no sync engines.
The Four Laws of Agent Access
- The agent can never see more than its owners -- delegated access inherits the owner's ACLs.
- Every data access is in the passport -- logged, auditable, visible in Observer.
- High-risk actions require owner approval -- no unilateral writes, merges, sends, or deletes.
- No owner, no agent -- agent is suspended if all owners are removed.
Owner Accountability
Every agent must have at least one Owner -- a human accountable for its existence, access, and behavior. Owners are managed through the Share dialog:
| Share Role | Permissions |
|---|---|
| Owner | Full control. Approve high-risk actions. Accountable in passport. At least one required. |
| Editor | Modify agent config and access. Cannot approve destructive actions. |
| Viewer | See agent activity and passport. Read-only. |
Architecture
The Agent Identity Stack
block-beta
columns 1
block:UX["UX Layer"]
UX1["'Share with agent' / @mention / Approve"]
end
block:GOV["Governance Layer"]
GOV1["Owner assignment (Share dialog)"]
GOV2["Policy-scoped detection overrides"]
GOV3["Approval flows ยท Delegation grants (OBO consent + TTL)"]
end
block:CRED["Credential Layer"]
CRED1["Autonomous (client credentials)"]
CRED2["OBO (token exchange)"]
CRED3["Provisioned (sidecar-injected secrets)"]
CRED4["Auto-rotation, JIT provisioning"]
end
block:AUTHZ["Authorization Layer"]
AUTHZ1["Cedar policies (generated from settings)"]
AUTHZ2["Verifier (inline Cedar enforcement)"]
AUTHZ3["Access Manifest (5-domain policy)"]
end
block:ID["Identity Layer"]
ID1["Workload identity per agent"]
ID2["OAuth client registration (per agent)"]
ID3["Agent email + handle + passport"]
ID4["Linked to owners"]
end
style UX fill:#e1f5fe
style GOV fill:#fff3e0
style CRED fill:#f3e5f5
style AUTHZ fill:#e8f5e9
style ID fill:#fce4ec
Three Auth Models
| Model | Name | When Used | Token Identifies |
|---|---|---|---|
| 1 | Autonomous Identity | Agent acts as itself -- cron jobs, A2A calls, MCP server connections | Agent only |
| 2 | OBO Delegation | Agent acts on behalf of a human via RFC 8693 token exchange | Agent + Human (act claim) |
| 3 | Provisioned Credentials | Human stores a secret, sidecar injects it -- agent never sees raw credentials | Depends on credential type |
Model 1: Autonomous Identity -- The agent authenticates as itself using a workload identity and obtains tokens via OAuth client_credentials grant. Used for cron jobs, A2A communication, and MCP server connections where the agent acts on its own authority.
Model 2: OBO Delegation -- The agent acts on behalf of a specific human using RFC 8693 token exchange. The sidecar exchanges the user's short-lived token and the agent's identity for a composite delegation token that identifies both the agent and the human, ensuring full attribution. All access is logged with human identity. Used for ad-hoc queries like "search my email" or "send a message as me."
Model 3: Provisioned Credentials -- A human stores a secret (API key, bot token, service account key) via the Connect modal, and the sidecar injects it into matching outbound requests. The agent runtime never sees the raw credential. Used when neither autonomous identity nor OBO delegation applies -- for example, a shared API key for a third-party service.
Credential Routing (Agent-Blind)
In the unified YAML definition, credential management uses agent-blind routing. The agent never sees credentials directly -- a sidecar proxy intercepts outbound requests, matches them to routing rules in environment.credentialRouting, and injects short-lived tokens from the secrets backend. This provides:
- Zero credential exposure to the agent runtime
- Automatic token rotation with configurable TTL
- Full audit trail of credential usage in the passport
Each routing rule specifies an injection_method that determines how the credential is obtained:
injection_method |
Behavior |
|---|---|
sidecar |
Default. Sidecar injects a stored credential from the secrets backend. Maps to Model 3. |
client_credentials |
Sidecar obtains a token via the agent's own OAuth client (SPIFFE-SVID assertion), caches it with TTL, and auto-refreshes. Maps to Model 1. |
token_exchange |
Sidecar performs an RFC 8693 exchange combining the user's token and the agent's SVID into a composite delegation token. Maps to Model 2. |
environment:
credentialRouting:
- destination: "*.googleapis.com"
credentialRef: google-drive-oauth
injectionMethod: sidecar
ttl: 15m
approval: auto
- destination: "*.slack.com"
injectionMethod: token_exchange
ttl: 15m
- destination: "mcp.internal.example.com"
injectionMethod: client_credentials
ttl: 1h
| Model | When | Example |
|---|---|---|
| Autonomous Identity | Agent acts on its own authority | Cron job syncs data, agent calls an MCP server |
| OBO Delegation | Agent acts for a specific human | "Search my email for the Acme contract" |
| Provisioned Credentials | Shared secret, no identity delegation | Agent uses an API key for a third-party service |
MCP Server Auth Discovery
When an MCP tool is installed from the app catalog, Lucid auto-discovers its auth requirements and registers the agent as an OAuth client. The flow uses two standards:
- Discovery (RFC 9728) -- The Verifier fetches the MCP server's Protected Resource Metadata endpoint to learn its authorization servers, token endpoint, supported scopes, and resource indicator.
- Registration (RFC 7591) -- The Verifier performs Dynamic Client Registration with the discovered authorization server, registering the agent as an OAuth client using its SPIFFE-SVID as the client assertion.
On successful discovery, the Verifier automatically creates a CredentialRoutingRule with injection_method: client_credentials targeting the MCP server's token endpoint, and stores the discovered metadata (authorization servers, scopes, resource indicators) in AppCatalogEntry.mcp_metadata. MCP servers that do not expose RFC 9728 metadata are skipped gracefully -- no error, no credential rule.
Delegation Grants
OBO delegation (Model 2) is governed by delegation grants that track active user-to-agent delegations. Each grant records:
- Who delegated to whom (user and agent)
- What was delegated -- service and scopes (e.g., Slack
chat:write) - When -- TTL-bounded lifetime with automatic expiry
- Revocation -- grants can be revoked immediately by owners
Consent cards appear inline in the chat when an agent requests OBO access mid-conversation. The user can Allow (creates a grant), Deny, or Customize (adjust scopes/duration). Resolved cards become read-only.
Active delegations are visible on the Delegations tab of the Approvals page, where owners can review grant details and revoke with one click. Pending consent requests surface in the Pending tab and increment the sidebar notification badge.
API: GET/POST/DELETE /v1/agents/{agent_id}/delegations.
How VAP Connects to Existing Systems
| System | VAP Role |
|---|---|
| Verifier | Routes requests, performs agent-blind credential injection, enforces Cedar access policies inline |
| Cedar Policies | Agent identity nodes become Cedar principals for fine-grained authorization |
| Evidence / Passport | Agent profile IS the passport -- rendered from attested evidence |
| ClaimsAuditors | Each auditor produces claims (observations); Verifier evaluates Cedar policy and bundles Evidence |
| Operator | Handles TEE pod deployment and mTLS sidecar injection |
| Quick Deploy | Extended with owner assignment, container selection, and auditor policy configuration |
App Catalog
The app catalog provides a browse-and-install store for agent capabilities. Think apt-get install but with a UI.
What's Installable
| Category | Examples | Source |
|---|---|---|
| MCP Servers | Slack, GitHub, Jira, Google Workspace, Salesforce | Lucid catalog + community |
| Auditors | Model Context, LLM Judge, custom auditors | Built-in + self-hosted registry |
| A2A Agents | Code reviewer, data analyst, translator | Agent registry |
| Skills | "Summarize PR", "Draft incident report", "Triage tickets" | Templates / prompt packs |
| Runtimes | Python sandbox, browser automation, code interpreter | Operator-managed containers |
Each app has: name, description, required permissions, trust tier, install count, and auditor requirements. Installing an app updates the agent's MCP tool list, auditor chain, or A2A connections.
API Endpoints
GET /v1/app-catalog # List available apps
GET /v1/app-catalog/{app_id} # Get app details
POST /v1/app-catalog/agents/{agent_id}/install # Install app
DELETE /v1/app-catalog/agents/{agent_id}/uninstall # Uninstall app
GET /v1/app-catalog/agents/{agent_id}/installed # List installed apps
App Properties
Each app has: name, description, category, type (mcp_server, auditor, a2a_agent, skill, runtime), trust tier, required permissions, and auditor requirements. Installing an app updates the agent's MCP tool list, auditor chain, or A2A connections. You can track which apps are installed per agent with configuration overrides.
VAP Console
A live window into the agent's Verifiable Agent Pod. Shows what the agent is doing right now, what its subagents are doing, and lets Owners interact.
Three Panels
- Log Stream -- Real-time structured logs from inside the TEE. Tool calls, model invocations, chain decisions, errors. Filterable by severity, auditor, subagent.
- Subagent Tree -- Visual tree of active subagents (if multi-agent). Each node shows: name, status, current task, resource usage. Click to drill into a subagent's logs.
- Interactive Shell -- Owner can send messages to the agent directly (like a chat in the terminal). Useful for debugging.
The console is read-only for Viewers. Editors can view logs. Only Owners can use the interactive shell (it is a control action, logged in the passport).
SSE Streaming API
The console log stream is powered by Server-Sent Events:
GET /v1/agents/{agent_id}/console/stream
Events are structured JSON with fields for timestamp, source agent, event type (tool_call, model_call, chain_decision, error, approval_requested), severity, and payload. The stream supports query parameters for filtering by severity, auditor, and subagent.
Detection and Response in AuditorPolicy
Detection settings and Cedar response rules live together in AuditorPolicy. Detection overrides are scoped per-policy and resolved by the Gateway at runtime.
Two Policy Concerns
| Concern | Model | Example |
|---|---|---|
| Cedar response rules | Deny-overrides (like AWS SCPs) | Org forbid rule cannot be overridden by workspace permit |
| Detection overrides | Per-policy overrides with enforcement modes | Policy sets injection_threshold: 0.5 with floor enforcement |
Resolution Order
For each detection field: start with @claims parameter default -> apply policy-scoped detection override -> result.
Chain Policy
Org and workspace admins can mandate specific auditors and compliance frameworks. These cascade and merge (never subtract):
System auditors (always) -> [model-context, llm-judge] Cannot remove
+ Org-required auditors -> [...] Cannot remove
+ Workspace-required auditors -> [...] Cannot remove
+ Framework-required auditors -> (from selected frameworks) Cannot remove
+ User-selected auditors -> [...] Can remove
= Final audit chain
System auditors (mandatory, every request): model-context, llm-judge. These run on every agent and cannot be removed.
Inheritance Lock Badges
Settings panels display inheritance context per field:
| Badge | Meaning | Behavior |
|---|---|---|
LOCKED (Set by Org Admin) |
Field enforced at org level | Disabled at workspace and agent level |
LOCKED (Set by Workspace) |
Field enforced at workspace level | Disabled at agent level |
INHERITED (from: org/workspace) |
Value inherited but overridable | Editable, with override/reset options |
OVERRIDDEN (org default: X) |
Value changed from parent | Shows parent's original value for reference |
DIRECT |
Set at this scope | Normal editable field |
Policy Management MCP Tool
AuditorPolicy detection overrides can be queried and modified at runtime via the auditor_policy MCP tool, which is exposed through the Verifier's MCP endpoint. This enables natural-language governance: an owner types "Give eng-assist read access to Slack and GitHub" in the Composer, and the LLM updates the AuditorPolicy via the MCP tool.
Structured Workspace Editor
The workspace editor provides a structured form view as the default, mapping to fields in the unified agent YAML definition. Raw YAML / markdown is available as an "Advanced" fallback.
File-Specific Editors
- Soul (
abilities.soul) -- Identity and personality. Sections: Identity (name, role), Personality (trait cards), Guidelines (rule cards), Custom sections. - Subagents (
abilities.subagents) -- Sub-agent definitions. Each sub-agent rendered as a card with name, description, delegation conditions, and permissions. - Tools (
environment.tools) -- Tool and MCP server definitions. Each tool is a card with name, category, configuration, and credential routing. - USER.md -- User context. Section-based: Preferences (key-value pairs), Context (free-form), Notes (entries).
Round-Trip Parsing
Structured Editor (default) <-> YAML / Markdown Editor (advanced)
| save | save
compile to YAML / markdown ----> store as spec fields / .md file
^ parse
parse from YAML / markdown <---- load from spec fields / .md file
Both directions are lossless. Custom or unrecognized sections are preserved as free-form blocks in the structured view.
Self-Hosted Auditors and Models
Organizations can run auditors and models on their own infrastructure, including TEE-enabled clusters. The Lucid Verifier acts as the Relying Party, validating hardware quotes remotely.
Three Deployment Modes
| Mode | Where | Trust Tier | Use Case |
|---|---|---|---|
| Sidecar | Same pod (operator-injected) | TEE-attested (highest) | Lucid-managed or customer CoCo cluster with Lucid Operator |
| In-cluster | Customer K8s, separate pod | mTLS-verified | Customer CoCo cluster, no Lucid Operator |
| External | Customer infrastructure (any) | mTLS or API-key (lowest) | Non-CoCo environments, on-prem, third-party providers |
Registration
Auditors: POST /v1/auditors/register with auditor_id, deployment_mode, endpoint/image, auth config, supported_phases, and vocabulary_url. After registration, the auditor appears in the catalog, agent creation wizard, and settings panels (auto-generated from @claims parameter metadata via the /vocabulary endpoint).
Models: POST /v1/models/register with model_id, deployment_mode, endpoint, auth config, model_type, and image digest. After registration, the model appears in the model catalog alongside Lucid-managed models.
CLI Developer Experience
# Scaffold a new auditor project
lucid auditor init my-auditor
# Local development with mock chain and hot-reload
lucid auditor dev
# Run contract compliance tests
lucid auditor test
# Register with the platform
lucid auditor register
# View all auditors with trust tier and status
lucid auditor list
# Inspect detection settings from @claims parameters
lucid auditor schema lucid-llm-judge-auditor
# Register a self-hosted model
lucid model register --endpoint https://my-model.example.com --mode external
# List all models (Lucid-managed + self-hosted)
lucid model list
# Verify remote attestation for a model
lucid model verify my-model-id
# Health check + inference smoke test
lucid model test my-model-id
SDK: Decorator-Based Schema Introspection
Detection settings are declared as keyword-only parameters on @claims-decorated methods. The SDK auto-introspects parameter names, types, and defaults to generate settings metadata for the Observer UI.
@claims Parameter Introspection
Settings metadata is auto-extracted from the decorator parameters and exposed via the /vocabulary endpoint:
from lucid_auditor_sdk import ClaimsAuditor, claims, Phase
from lucid_schemas import Claim
class MyAuditor(ClaimsAuditor):
def __init__(self):
super().__init__("my-auditor", "1.0.0")
@claims(phase=Phase.REQUEST, produces=["threat_score", "threat_detected"])
def check_input(
self, data: dict, *,
threshold: float = 0.8,
scan_enabled: bool = True,
) -> list[Claim]:
score = self.analyze(data)
return [
Claim(name="threat_score", type="score_normalized", value=score),
Claim(name="threat_detected", type="boolean", value=score > threshold),
]
# provenance auto-stamped: {"threshold": 0.8, "scan_enabled": true}
The metadata drives the auto-generated settings panels in the Observer UI, rendering settings as collapsible sections.
Detection Overrides via AuditorPolicy.detection
Detection overrides are stored in AuditorPolicy.detection alongside Cedar response rules. The Gateway resolves overrides from the policy and injects them into @claims method parameters at runtime:
{
"detection_overrides": {
"threat_score": { "threshold": 0.5, "scan_enabled": true }
}
}
Auditors receive the effective parameter values transparently -- no manual lookup required.
What's Next
- See the CLI Reference for all auditor and model commands.
- See the SDK Reference for
@claimsparameter API docs. - See the Verifier API for app catalog, console, and auditor settings endpoints.
- See the Glossary for VAP terminology definitions.