Skip to main content

Agents & Policies

Agents represent AI applications registered in your workspace. Policies bind agents to connections and define what the agent is allowed to do -- execution models, access modes, allowlists, rate limits, time windows, and custom rules.

Agents

Endpoint Summary

MethodEndpointDescription
POST/v1/agentsCreate agent (returns bootstrap secret)
GET/v1/agentsList agents
GET/v1/agents/:idGet agent by ID
PUT/v1/agents/:idUpdate agent
DELETE/v1/agents/:idDelete agent (cascades to policies)
POST/v1/agents/:id/bootstrap-secretGenerate a bootstrap secret for enrollment or key rotation
POST/v1/agents/:id/disableDisable agent (revokes all tokens)
POST/v1/agents/:id/enableRe-enable a disabled agent

Agent Lifecycle

Agents follow a three-state lifecycle:

StateDescription
createdAgent registered but not yet enrolled (awaiting public key)
activeAgent enrolled with an ES256 public key; can authenticate and call the Vault
disabledAgent suspended; all access tokens revoked, new token exchange rejected

Transitions: createdactive (via bootstrap) → disabled (via disable endpoint) → active (via enable endpoint). Re-bootstrapping an active agent replaces the public key and invalidates all tokens without changing state.

Create Agent

POST /v1/agents

Creates a new agent and returns a one-time bootstrap secret. The agent must complete the bootstrap flow within 1 hour to become active.

Request:

{
"name": "Email Assistant",
"description": "Reads and drafts emails on behalf of the user",
"iconUrl": "https://example.com/icon.png"
}
FieldRequiredDescription
nameYesAgent name (non-empty string)
descriptionNoAgent description
iconUrlNoURL for the agent icon

Response:

{
"agent": {
"id": "uuid",
"name": "Email Assistant",
"description": "Reads and drafts emails on behalf of the user",
"iconUrl": "https://example.com/icon.png",
"status": "created",
"enrolledAt": null,
"createdAt": "2025-06-01T00:00:00Z"
},
"bootstrapSecret": "ah5b_aBcDeFgHiJkLmNoPqRsTuVwXyZ..."
}

The bootstrapSecret is shown only once on creation and cannot be retrieved later. Only the SHA-256 hash is stored. The secret expires in 1 hour (configurable via BOOTSTRAP_SECRET_TTL_HOURS).

List Agents

GET /v1/agents

Returns all agents in the current workspace. Each agent includes a status field (created, active, or disabled).

Get Agent by ID

GET /v1/agents/:id

Returns agent details including status, enrolledAt (null if not yet enrolled), and updatedAt.

Update Agent

PUT /v1/agents/:id

Updates name, description, and/or icon URL. At least one field must be provided.

Delete Agent

DELETE /v1/agents/:id

Permanently deletes an agent. Associated policies, access tokens, and approval requests are removed via cascading foreign keys.

Generate Bootstrap Secret

POST /v1/agents/:id/bootstrap-secret

Generates a one-time bootstrap secret for agent enrollment or key rotation. Works for agents in created or active status (rejects disabled agents).

Response:

{
"bootstrapSecret": "ah5b_aBcDeFgHiJkLmNoPqRsTuVwXyZ..."
}

The bootstrap secret expires in 1 hour (configurable via BOOTSTRAP_SECRET_TTL_HOURS). When the agent completes the bootstrap flow, the public key is registered (or replaced) and any existing access tokens are invalidated.

Disable Agent

POST /v1/agents/:id/disable

Disables the agent immediately. All outstanding access tokens are deleted and new token exchanges are rejected. Returns the updated agent.

Enable Agent

POST /v1/agents/:id/enable

Re-enables a disabled agent. If the agent has a public key on file, the status returns to active. If not (e.g., never enrolled), the status returns to created. Returns the updated agent.


Policies

A policy is a binding between an agent and a connection. It controls which execution models are allowed, the access mode, step-up approval behavior, and fine-grained rules.

Endpoint Summary

MethodEndpointDescription
POST/v1/policiesCreate policy
GET/v1/policiesList policies
PUT/v1/policies/:idUpdate policy settings
PUT/v1/policies/:id/allowlistsSet allowlist rules
PUT/v1/policies/:id/rate-limitsSet rate limits
PUT/v1/policies/:id/time-windowsSet time windows
GET/v1/policies/:id/rulesGet policy rules
PUT/v1/policies/:id/rulesSet policy rules
PUT/v1/policies/:id/provider-constraintsSet provider constraints (chat/channel restrictions)
DELETE/v1/policies/:idDelete policy

Create Policy

POST /v1/policies

Creates a policy binding between an agent and a connection. Both must belong to the current workspace.

Allowlists are auto-populated with service-specific defaults based on the connection's service (e.g., a Gmail connection gets allowlists scoped to https://www.googleapis.com/gmail/v1/*, a Telegram connection gets https://api.telegram.org/bot*/*). This means newly created policies work out of the box for Model B execution. You can customize allowlists later via PUT /v1/policies/:id/allowlists.

Request:

{
"agentId": "uuid",
"connectionId": "uuid",
"allowedModels": ["A", "B"],
"defaultMode": "read_only",
"stepUpApproval": "risk_based"
}
FieldRequiredDefaultDescription
agentIdYes--Agent to bind
connectionIdYes--Connection to bind
allowedModelsNo["A", "B"]Execution models: "A" (token vending), "B" (brokered proxy)
defaultModeNo"read_only"Access mode: read_only, read_write, custom
stepUpApprovalNo"risk_based"Approval mode: always, risk_based, never

List Policies

GET /v1/policies

Returns all policies for the current workspace (scoped through workspace agents).

Update Policy

PUT /v1/policies/:id

Updates allowedModels, defaultMode, and/or stepUpApproval.

Delete Policy

DELETE /v1/policies/:id

Removes the policy binding. The agent will no longer have access through this connection.


Set Allowlists

PUT /v1/policies/:id/allowlists

Configures URL allowlists for Model B execution. Requests that do not match any allowlist entry are denied (default-deny).

Request:

{
"allowlists": [
{
"baseUrl": "https://gmail.googleapis.com",
"methods": ["GET"],
"pathPatterns": ["/gmail/v1/users/me/messages/*", "/gmail/v1/users/me/labels"]
},
{
"baseUrl": "https://gmail.googleapis.com",
"methods": ["POST"],
"pathPatterns": ["/gmail/v1/users/me/messages/send"]
}
]
}
FieldRequiredDescription
baseUrlYesHTTPS base URL (HTTP is rejected)
methodsYesAllowed HTTP methods: GET, POST, PUT, DELETE, PATCH
pathPatternsYesURL path patterns with wildcard support (e.g., /users/me/messages/*)

Path pattern matching: * at the end of a pattern matches any suffix. For example, /users/me/messages/* matches /users/me/messages/123 and /users/me/messages/123/attachments.


Set Rate Limits

PUT /v1/policies/:id/rate-limits

Configures rate limits and size constraints. Pass null for rateLimits to remove all limits.

Request:

{
"rateLimits": {
"maxRequestsPerHour": 100,
"maxPayloadSizeBytes": 1048576,
"maxResponseSizeBytes": 10485760
}
}
FieldRequiredDescription
maxRequestsPerHourYes (if setting limits)Max requests per hour per agent+connection pair
maxPayloadSizeBytesNoMax request body size in bytes
maxResponseSizeBytesNoMax response size in bytes

Rate limits are enforced per agent+connection pair using audit event counts from the past hour.


Set Time Windows

PUT /v1/policies/:id/time-windows

Restricts execution to specific time windows. Requests outside all configured windows are denied.

Request:

{
"timeWindows": [
{
"dayOfWeek": 1,
"startHour": 9,
"endHour": 17,
"timezone": "America/New_York"
},
{
"dayOfWeek": 2,
"startHour": 9,
"endHour": 17,
"timezone": "America/New_York"
}
]
}
FieldRequiredDescription
dayOfWeekYes0 = Sunday, 1 = Monday, ..., 6 = Saturday
startHourYesStart hour (0-23, inclusive)
endHourYesEnd hour (0-23, inclusive)
timezoneYesIANA timezone (e.g., America/New_York, Europe/London)

Pass an empty array to remove all time window restrictions.


Get/Set Policy Rules

GET /v1/policies/:id/rules
PUT /v1/policies/:id/rules

Policy rules provide fine-grained request evaluation (pre-execution) and response filtering (post-execution).

Request rules are evaluated before execution. First match wins with action: allow, deny, or require_approval.

Response rules filter the provider response before returning to the agent (field allowlists, denylists, and PII redaction).

PUT request body:

{
"rules": {
"request": [
{
"label": "Block delete operations",
"match": {
"methods": ["DELETE"],
"urlPattern": ".*"
},
"action": "deny"
},
{
"label": "Require approval for sending emails",
"match": {
"methods": ["POST"],
"urlPattern": ".*/messages/send"
},
"action": "require_approval"
}
],
"response": [
{
"label": "Redact PII from responses",
"match": {
"urlPattern": ".*/messages/.*",
"methods": ["GET"]
},
"filter": {
"redact": [
{ "type": "email" },
{ "type": "phone" },
{ "type": "ssn" }
]
}
}
]
}
}

Request rule match conditions:

FieldDescription
methodsHTTP methods to match
urlPatternRegex pattern matched against the URL path
bodyArray of body field matchers with path, op (eq, neq, in, not_in, contains, matches, exists), and value

Response filter options:

FieldDescription
allowFieldsOnly include these fields in the response
denyFieldsRemove these fields from the response
redactPII redaction rules: email, phone, ssn, credit_card, ip_address, or custom with a regex pattern and replacement

Update Provider Constraints

PUT /v1/policies/:id/provider-constraints

Sets provider-specific access constraints. These restrict which chats, channels, or tenants an agent can interact with through a connection.

Telegram constraints are bidirectional: they restrict both who can send messages to the agent and who the agent can send to. If allowedChatIds is empty, all users are allowed (open).

Microsoft Teams constraints are opt-in: if not configured, all chats/channels/tenants are allowed.

Slack constraints support two dimensions — channels and users. allowedChannelIds restricts which channels the agent can read from and post to. allowedUserIds filters inbound messages to only show messages from allowed users. If either is empty or omitted, no restriction is applied for that dimension.

Request body (Telegram):

{
"providerConstraints": {
"provider": "telegram",
"allowedChatIds": ["-1001234567890", "987654321"]
}
}

Request body (Microsoft Teams):

{
"providerConstraints": {
"provider": "microsoft",
"allowedTenantIds": ["tenant-uuid"],
"allowedChatIds": ["chat-id"],
"allowedChannelIds": ["channel-id"]
}
}

Request body (Slack):

{
"providerConstraints": {
"provider": "slack",
"allowedChannelIds": ["C0123456789", "C9876543210"],
"allowedUserIds": ["U0123456789"]
}
}

Pass null to clear all constraints:

{ "providerConstraints": null }

The provider field must match the connection's provider. Setting Telegram constraints on a Google connection returns 400.

Templates

Pre-built allowlist templates and rule presets are available via the Templates endpoints:

MethodEndpointDescription
GET/v1/templates/:providerGet allowlist templates for a provider
GET/v1/templates/:provider/rulesGet rule presets (minimal/standard/strict) and individual rule templates
GET/v1/templates/:provider/guardsGet contextual security guards by action category

Supported providers: google, microsoft, telegram, slack.