Skip to content

Latest commit

 

History

History
1699 lines (1149 loc) · 80 KB

File metadata and controls

1699 lines (1149 loc) · 80 KB

Interchange Hub API

Endpoint Index

Method Path Summary
GET /api/me Get current user profile
GET /api/me/principals List principals across all tenants
GET /api/me/agents List agents across all tenants
GET /api/me/instances List running agent instances across all tenants
GET /api/me/sessions List sessions across all tenants
GET /api/me/approvals List pending approvals across all tenants
GET /api/me/git-tokens List personal git tokens
POST /api/me/git-tokens Mint a personal access git token
DELETE /api/me/git-tokens/:tokenId Revoke a personal git token
POST /api/tenants Create a tenant
GET /api/tenants/:tenantId Get tenant details
PATCH /api/tenants/:tenantId Update tenant config
GET /api/tenants/:tenantId/principals List principals in the tenant
GET /api/tenants/:tenantId/principals/:principalId Get principal details
PATCH /api/tenants/:tenantId/principals/:principalId Update principal status
DELETE /api/tenants/:tenantId/principals/:principalId Remove principal from tenant
POST /api/tenants/:tenantId/members/invite Invite a user to the tenant
GET /api/tenants/:tenantId/roles List roles in the tenant
POST /api/tenants/:tenantId/roles Create a custom role
GET /api/tenants/:tenantId/roles/:roleId Get role details
PATCH /api/tenants/:tenantId/roles/:roleId Update a role
DELETE /api/tenants/:tenantId/roles/:roleId Delete a custom role
POST /api/tenants/:tenantId/principals/:principalId/roles/:roleId Assign a role to a principal
DELETE /api/tenants/:tenantId/principals/:principalId/roles/:roleId Remove a role from a principal
GET /api/tenants/:tenantId/grants List grants in the tenant
POST /api/tenants/:tenantId/grants Create a grant
GET /api/tenants/:tenantId/grants/:grantId Get grant details
PATCH /api/tenants/:tenantId/grants/:grantId Update a grant
DELETE /api/tenants/:tenantId/grants/:grantId Revoke a grant
POST /api/tenants/:tenantId/principals/:principalId/evaluate Evaluate grants for a principal
GET /api/tenants/:tenantId/agents/definitions List agents in the tenant
POST /api/tenants/:tenantId/agents/definitions Create an agent
GET /api/tenants/:tenantId/agents/definitions/:agentId Get agent details
PATCH /api/tenants/:tenantId/agents/definitions/:agentId Update agent definition
DELETE /api/tenants/:tenantId/agents/definitions/:agentId Retire an agent
GET /api/tenants/:tenantId/agents/definitions/:agentId/versions List agent versions
POST /api/tenants/:tenantId/agents/definitions/:agentId/rollback Rollback to a previous version
POST /api/tenants/:tenantId/agents/instances Deploy an agent instance
GET /api/tenants/:tenantId/agents/instances List agent instances
GET /api/tenants/:tenantId/agents/instances/blobs/:blobId Fetch a blob by ID
GET /api/tenants/:tenantId/agents/instances/:instanceId Get instance detail
DELETE /api/tenants/:tenantId/agents/instances/:instanceId Stop an instance
GET /api/tenants/:tenantId/agents/instances/:instanceId/health Get instance health
GET /api/tenants/:tenantId/agents/instances/:instanceId/offerings List instance offerings
GET /api/tenants/:tenantId/agents/instances/:instanceId/events SSE event stream
POST /api/tenants/:tenantId/agents/instances/:instanceId/mail Send mail to the agent
GET /api/tenants/:tenantId/agents/instances/:instanceId/mail List mail for an instance
GET /api/tenants/:tenantId/agents/instances/:instanceId/turns List inference turns for an instance
POST /api/tenants/:tenantId/workflows/instances Deploy a workflow
GET /api/tenants/:tenantId/workflows/instances List workflow deployments
POST /api/tenants/:tenantId/workflows/:deploymentId/signals Deliver a signal to a workflow run
POST /api/tenants/:tenantId/workflows/:deploymentId/mail Trigger a workflow run
GET /api/tenants/:tenantId/workflows/:deploymentId/runs List workflow runs
GET /api/tenants/:tenantId/workflows/:deploymentId/runs/:runId/events Read a workflow run's event log
GET /api/tenants/:tenantId/approvals List pending approvals in the tenant
GET /api/tenants/:tenantId/approvals/:approvalId Get approval details
POST /api/tenants/:tenantId/approvals/:approvalId/approve Approve an action
POST /api/tenants/:tenantId/approvals/:approvalId/reject Reject an action
GET /api/tenants/:tenantId/wallets List wallets in the tenant
POST /api/tenants/:tenantId/wallets Create a wallet
GET /api/tenants/:tenantId/wallets/:walletId Get wallet details
PATCH /api/tenants/:tenantId/wallets/:walletId Update wallet config
DELETE /api/tenants/:tenantId/wallets/:walletId Deactivate a wallet
GET /api/tenants/:tenantId/wallets/:walletId/transactions List transactions
GET /api/tenants/:tenantId/providers List providers
POST /api/tenants/:tenantId/providers Create a provider definition
GET /api/tenants/:tenantId/providers/:providerId Get provider details
PATCH /api/tenants/:tenantId/providers/:providerId Update a provider definition
DELETE /api/tenants/:tenantId/providers/:providerId Remove a provider definition
GET /api/tenants/:tenantId/oauth-clients List OAuth client registrations
POST /api/tenants/:tenantId/oauth-clients Register an OAuth client
GET /api/tenants/:tenantId/oauth-clients/:oauthClientId Get OAuth client details
PATCH /api/tenants/:tenantId/oauth-clients/:oauthClientId Update an OAuth client registration
DELETE /api/tenants/:tenantId/oauth-clients/:oauthClientId Remove an OAuth client registration
GET /api/tenants/:tenantId/credentials List credentials
POST /api/tenants/:tenantId/credentials Store a credential
GET /api/tenants/:tenantId/credentials/resolve/:name Resolve a credential by name
GET /api/tenants/:tenantId/credentials/:credentialId Get credential metadata
PATCH /api/tenants/:tenantId/credentials/:credentialId Rotate or update a credential
DELETE /api/tenants/:tenantId/credentials/:credentialId Revoke a credential
GET /api/tenants/:tenantId/offerings Search offerings
POST /api/tenants/:tenantId/offerings Register an offering
GET /api/tenants/:tenantId/offerings/:offeringId Get offering details
PATCH /api/tenants/:tenantId/offerings/:offeringId Update an offering
DELETE /api/tenants/:tenantId/offerings/:offeringId Remove an offering
GET /api/tenants/:tenantId/catalog/models List models owned by the tenant
POST /api/tenants/:tenantId/catalog/models Create a model
GET /api/tenants/:tenantId/catalog/models/:modelId Get a model
PATCH /api/tenants/:tenantId/catalog/models/:modelId Update a model
DELETE /api/tenants/:tenantId/catalog/models/:modelId Delete a model
GET /api/tenants/:tenantId/catalog/providers List model providers owned by the tenant
POST /api/tenants/:tenantId/catalog/providers Create a model provider
GET /api/tenants/:tenantId/catalog/providers/:providerId Get a model provider
PATCH /api/tenants/:tenantId/catalog/providers/:providerId Update a model provider
DELETE /api/tenants/:tenantId/catalog/providers/:providerId Delete a model provider
GET /api/tenants/:tenantId/catalog/offerings List model offerings owned by the tenant
POST /api/tenants/:tenantId/catalog/offerings Create a model offering
GET /api/tenants/:tenantId/catalog/offerings/:offeringId Get a model offering
PATCH /api/tenants/:tenantId/catalog/offerings/:offeringId Update a model offering
DELETE /api/tenants/:tenantId/catalog/offerings/:offeringId Delete a model offering
GET /api/tenants/:tenantId/catalog/offerings/:offeringId/pricing List an offering's pricing history
POST /api/tenants/:tenantId/catalog/offerings/:offeringId/pricing Add a pricing row to an offering
GET /api/tenants/:tenantId/models List the models resolved for the tenant
GET /api/tenants/:tenantId/git-tokens List tenant git tokens
POST /api/tenants/:tenantId/git-tokens Mint a tenant-bound service git token
DELETE /api/tenants/:tenantId/git-tokens/:tokenId Revoke a tenant git token
GET /api/tenants/:tenantId/agents/:agentId/logs Get agent logs
GET /api/tenants/:tenantId/agents/:agentId/metrics Get agent metrics
GET /api/tenants/:tenantId/traces Query distributed traces
GET /api/tenants/:tenantId/traces/:traceId Get a full trace
GET /api/tenants/:tenantId/federation List federation trust relationships
POST /api/tenants/:tenantId/federation Establish federation trust
DELETE /api/tenants/:tenantId/federation/:targetTenantId Revoke federation trust
GET /api/tenants/:tenantId/agents/:agentId/data List files in agent working directory
GET /api/tenants/:tenantId/agents/:agentId/data/* Read a file from agent storage
GET /api/tenants/:tenantId/agents/:agentId/history List commits and checkpoints
GET /api/tenants/:tenantId/agents/:agentId/history/:ref Show changes in a commit
GET /api/tenants/:tenantId/agents/:agentId/branches List branches
POST /api/tenants/:tenantId/agents/:agentId/history/:ref/restore Restore agent data to a previous state
GET /api/tenants/:tenantId/assets List assets
POST /api/tenants/:tenantId/assets Create an asset
GET /api/tenants/:tenantId/assets/:assetId Get asset metadata
PUT /api/tenants/:tenantId/assets/:assetId/tarballs/:filename Upload a tarball into a package-registry asset
DELETE /api/tenants/:tenantId/assets/:assetId/tarballs/:filename Delete a tarball from a package-registry asset
GET /api/tenants/:tenantId/assets/:assetId/tarballs List tarballs in a package-registry asset

User

GET /api/me

Get current user profile

200: UserProfile -- User profile 401: ErrorResponse -- Not authenticated

GET /api/me/principals

List principals across all tenants

Returns all of the authenticated user's principals across tenants, with tenant name, roles, and status in each.

Query: cursor?, limit?

200: unknown -- List of principals across tenants 401: ErrorResponse -- Not authenticated

GET /api/me/agents

List agents across all tenants

Aggregates agents from all tenants the user belongs to. Each result is tagged with tenantId.

Query: cursor?, limit?

200: unknown -- Agents across tenants

GET /api/me/instances

List running agent instances across all tenants

Aggregates running agent instances from all tenants the user belongs to. Each result is tagged with tenantId.

Query: cursor?, limit?

200: unknown -- Instances across tenants

GET /api/me/sessions

List sessions across all tenants

Aggregates active sessions from all tenants the user belongs to. Each result is tagged with tenantId.

200: SessionSummary[] -- Sessions across tenants

GET /api/me/approvals

List pending approvals across all tenants

Aggregates pending approval requests from all tenants the user belongs to. Each result is tagged with tenantId.

200: ApprovalSummary[] -- Approvals across tenants

Git Tokens

GET /api/me/git-tokens

List personal git tokens

Lists the authenticated user's personal access tokens (kind: "pat"). Secrets are never returned; the plaintext is shown only at mint time.

Query: cursor?, limit?

200: unknown -- List of git tokens 401: ErrorResponse -- Not authenticated

POST /api/me/git-tokens

Mint a personal access git token

Mints a personal access token (kind: "pat") for the authenticated user. The plaintext secret is returned exactly once in the response. An optional tenantId restricts the token to a single tenant.

Body: unknown

201: unknown -- Token minted 400: ErrorResponse -- Validation error 401: ErrorResponse -- Not authenticated

DELETE /api/me/git-tokens/:tokenId

Revoke a personal git token

Soft-revokes a personal access token by setting revokedAt. Only the owning user may revoke their own tokens.

204: (no content) -- Token revoked 401: ErrorResponse -- Not authenticated 403: ErrorResponse -- Token not owned by the authenticated user 404: ErrorResponse -- Token not found

GET /api/tenants/:tenantId/git-tokens

List tenant git tokens

Lists service tokens (kind: "svc") bound to this tenant. Secrets are never returned; the plaintext is shown only at mint time.

Query: cursor?, limit?

200: unknown -- List of git tokens

POST /api/tenants/:tenantId/git-tokens

Mint a tenant-bound service git token

Mints a service token (kind: "svc") bound to the requesting tenant. The plaintext secret is returned exactly once in the response and is never persisted in plaintext.

Body: unknown

201: unknown -- Token minted 400: ErrorResponse -- Validation error

DELETE /api/tenants/:tenantId/git-tokens/:tokenId

Revoke a tenant git token

Soft-revokes a tenant-bound git token by setting revokedAt. The row is retained for audit.

204: (no content) -- Token revoked 404: ErrorResponse -- Token not found

Tenants

POST /api/tenants

Create a tenant

Creates a new tenant. The authenticated user becomes the owner with a principal and default owner role.

Body: CreateTenant

201: TenantResponse -- Tenant created 400: ErrorResponse -- Validation error

GET /api/tenants/:tenantId

Get tenant details

200: TenantResponse -- Tenant details 403: ErrorResponse -- Not a member of this tenant 404: ErrorResponse -- Tenant not found

PATCH /api/tenants/:tenantId

Update tenant config

Requires admin or higher grant within the tenant.

Body: UpdateTenant

200: TenantResponse -- Tenant updated 403: ErrorResponse -- Insufficient grants

GET /api/tenants/:tenantId/federation

List federation trust relationships

Query: cursor?, limit?

200: unknown -- Federation trusts

POST /api/tenants/:tenantId/federation

Establish federation trust

Creates a trust relationship with another tenant for cross-tenant agent discovery and interaction.

Body: CreateFederationTrust

201: FederationTrust -- Trust established 400: ErrorResponse -- Validation error

DELETE /api/tenants/:tenantId/federation/:targetTenantId

Revoke federation trust

204: (no content) -- Trust revoked 404: ErrorResponse -- Trust not found

Principals

GET /api/tenants/:tenantId/principals

List principals in the tenant

Lists all principals (users and agents) in the tenant. Filterable by kind and status.

Query: kind?: user|agent, status?: active|suspended|invited|deactivated, cursor?, limit?

200: unknown -- List of principals

GET /api/tenants/:tenantId/principals/:principalId

Get principal details

Returns principal details including kind, status, assigned roles, and effective grants.

200: PrincipalResponse -- Principal details 404: ErrorResponse -- Principal not found

PATCH /api/tenants/:tenantId/principals/:principalId

Update principal status

Activate, suspend, or deactivate a principal.

Body: UpdatePrincipal

200: PrincipalResponse -- Principal updated 403: ErrorResponse -- Insufficient grants

DELETE /api/tenants/:tenantId/principals/:principalId

Remove principal from tenant

Removes a user or agent principal from the tenant. For agents, use agent deletion instead.

204: (no content) -- Principal removed 403: ErrorResponse -- Insufficient grants

POST /api/tenants/:tenantId/members/invite

Invite a user to the tenant

Invites a user by email. Creates a principal with invited status and optionally assigns a role.

Body: InviteMember

201: PrincipalResponse -- Invitation sent 400: ErrorResponse -- Validation error

Roles

GET /api/tenants/:tenantId/roles

List roles in the tenant

Lists both system roles (owner, admin, member) and custom roles.

Query: cursor?, limit?

200: unknown -- List of roles

POST /api/tenants/:tenantId/roles

Create a custom role

Body: CreateRole

201: RoleResponse -- Role created 400: ErrorResponse -- Validation error

GET /api/tenants/:tenantId/roles/:roleId

Get role details

Returns role details including attached grants.

200: RoleResponse -- Role details 404: ErrorResponse -- Role not found

PATCH /api/tenants/:tenantId/roles/:roleId

Update a role

Update name or description. System roles cannot be modified.

Body: UpdateRole

200: RoleResponse -- Role updated 403: ErrorResponse -- Cannot modify system role

DELETE /api/tenants/:tenantId/roles/:roleId

Delete a custom role

Deletes a custom role. Fails if principals are currently assigned to it. System roles cannot be deleted.

204: (no content) -- Role deleted 400: ErrorResponse -- Role still assigned to principals 403: ErrorResponse -- Cannot delete system role

POST /api/tenants/:tenantId/principals/:principalId/roles/:roleId

Assign a role to a principal

Assigns a role to a user or agent principal within the tenant.

204: (no content) -- Role assigned 404: ErrorResponse -- Principal or role not found

DELETE /api/tenants/:tenantId/principals/:principalId/roles/:roleId

Remove a role from a principal

204: (no content) -- Role removed 404: ErrorResponse -- Assignment not found

Grants

GET /api/tenants/:tenantId/grants

List grants in the tenant

Lists all grants. Filterable by principalId, roleId, resource pattern, and effect.

Query: principalId?, roleId?, resource?, effect?: allow|deny|ask, cursor?, limit?

200: unknown -- List of grants

POST /api/tenants/:tenantId/grants

Create a grant

Creates a grant targeting either a role or a principal directly. Exactly one of roleId or principalId must be provided.

Body: CreateGrant

201: GrantResponse -- Grant created 400: ErrorResponse -- Validation error

GET /api/tenants/:tenantId/grants/:grantId

Get grant details

200: GrantResponse -- Grant details 404: ErrorResponse -- Grant not found

PATCH /api/tenants/:tenantId/grants/:grantId

Update a grant

Update effect, conditions, or expiry on an existing grant.

Body: UpdateGrant

200: GrantResponse -- Grant updated 404: ErrorResponse -- Grant not found

DELETE /api/tenants/:tenantId/grants/:grantId

Revoke a grant

204: (no content) -- Grant revoked 404: ErrorResponse -- Grant not found

POST /api/tenants/:tenantId/principals/:principalId/evaluate

Evaluate grants for a principal

Evaluates what would happen if a principal attempted an operation. Returns the resolved effect and all matching grants. Useful for debugging authorization.

Body: EvaluateRequest

200: EvaluateResult -- Evaluation result 404: ErrorResponse -- Principal not found

Agents

GET /api/tenants/:tenantId/agents/definitions

List agents in the tenant

Filterable by offering and status.

Query: offering?, status?: deployed|stopped, cursor?, limit?

200: unknown -- List of agents

POST /api/tenants/:tenantId/agents/definitions

Create an agent

Creates an agent definition. Grant requirements are stored as a manifest and resolved at instance launch time.

Body: CreateAgent

201: AgentResponse -- Agent created 400: ErrorResponse -- Validation error

GET /api/tenants/:tenantId/agents/definitions/:agentId

Get agent details

Returns the agent definition, status, health, and capabilities.

200: AgentResponse -- Agent details 404: ErrorResponse -- Agent not found

PATCH /api/tenants/:tenantId/agents/definitions/:agentId

Update agent definition

Updates the agent definition and creates a new version. The new version is deployed alongside the current version until health checks pass.

Body: UpdateAgent

200: AgentResponse -- Agent updated 400: ErrorResponse -- Validation error

DELETE /api/tenants/:tenantId/agents/definitions/:agentId

Retire an agent

Retires the agent definition and marks all running instances as stopped. Does not signal running sidecars; in-flight sessions continue until the sidecar disconnects.

204: (no content) -- Agent retirement initiated 404: ErrorResponse -- Agent not found

GET /api/tenants/:tenantId/agents/definitions/:agentId/versions

List agent versions

Lists all versions with their deployment status.

Query: cursor?, limit?

200: unknown -- List of versions

POST /api/tenants/:tenantId/agents/definitions/:agentId/rollback

Rollback to a previous version

Shifts traffic back to the specified version. The current version is stopped.

Body: RollbackRequest

200: AgentResponse -- Rollback initiated 400: ErrorResponse -- Invalid version

Instances

POST /api/tenants/:tenantId/agents/instances

Deploy an agent instance

Creates a new running instance of the specified agent definition. Resolves the definition's model requirements against the tenant catalog into an ordered inference-source list, materializes grants on a new agent principal, provisions the agent on a sidecar, and starts it. The invoker can provide invokerGrants to delegate additional capabilities, and modelPreferences to reorder or restrict the resolved providers for the session.

Body: CreateAgentInstance

201: AgentInstanceResponse -- Instance deployed 404: ErrorResponse -- Agent definition not found 409: ErrorResponse -- Agent not launchable 502: ErrorResponse -- Sidecar unavailable

GET /api/tenants/:tenantId/agents/instances

List agent instances

Lists agent instances in the tenant. Filterable by agentId and status.

Query: agentId?, status?: deployed|running|updating|error|stopped, cursor?, limit?

200: unknown -- List of instances

GET /api/tenants/:tenantId/agents/instances/blobs/:blobId

Fetch a blob by ID

Returns raw bytes for a MIME part. Blob IDs are issued by the mail parsing layer.

200: (no content) -- Blob bytes 400: ErrorResponse -- Invalid blob ID 403: ErrorResponse -- Forbidden 404: ErrorResponse -- Blob not found

GET /api/tenants/:tenantId/agents/instances/:instanceId

Get instance detail

Returns instance runtime state including status, public key, and sidecar assignment.

200: AgentInstanceResponse -- Instance detail 404: ErrorResponse -- Instance not found

DELETE /api/tenants/:tenantId/agents/instances/:instanceId

Stop an instance

Stops the running instance and undeploys the agent from the sidecar.

204: (no content) -- Instance stopped 404: ErrorResponse -- Instance not found 409: ErrorResponse -- Instance already stopped 502: ErrorResponse -- Sidecar unavailable

GET /api/tenants/:tenantId/agents/instances/:instanceId/health

Get instance health

Returns liveness and readiness for a running instance. Liveness reflects whether the instance's sidecar connection is active. Readiness reflects whether the instance has an active event collector and can process work.

200: AgentHealth -- Health status 404: ErrorResponse -- Instance not found 410: ErrorResponse -- Instance stopped

GET /api/tenants/:tenantId/agents/instances/:instanceId/offerings

List instance offerings

Returns the offerings associated with the instance's agent definition. These represent the capabilities the instance can provide.

200: OfferingDetail[] -- List of offerings 404: ErrorResponse -- Instance not found

GET /api/tenants/:tenantId/agents/instances/:instanceId/events

SSE event stream

Server-Sent Events stream for agent events. Use POST .../messages for client-to-server messaging.

200: SSE stream -- SSE event stream 404: ErrorResponse -- Instance not found 410: ErrorResponse -- Instance stopped

POST /api/tenants/:tenantId/agents/instances/:instanceId/mail

Send mail to the agent

Persists the user message as a mail record and dispatches it to the running agent. Returns JMAP Email-shaped response.

Body: SendMessage

201: MailResponse -- Mail sent 400: AttachmentErrorResponse -- Attachment validation error. Each variant carries a structured code (oversize_attachment, disallowed_mime_type, malformed_base64, oversize_total) with the offending index and limits. A malformed request body that fails SendMessage validation returns the generic error shape instead. 404: ErrorResponse -- Instance not found 409: ErrorResponse -- Instance not running 413: ErrorResponse -- Request body exceeds the maximum allowed size 502: ErrorResponse -- Sidecar unavailable

GET /api/tenants/:tenantId/agents/instances/:instanceId/mail

List mail for an instance

Returns parsed JMAP Email objects in reverse chronological order. Cursor-paginated.

Query: cursor?, limit?

200: unknown -- List of mail 404: ErrorResponse -- Instance not found

GET /api/tenants/:tenantId/agents/instances/:instanceId/turns

List inference turns for an instance

Returns inference turns with their parts in reverse chronological order. Cursor-paginated.

Query: cursor?, limit?

200: unknown -- List of inference turns 404: ErrorResponse -- Instance not found

Workflows

POST /api/tenants/:tenantId/workflows/instances

Deploy a workflow

Hydrates a workflow definition from its workflow asset's workflow.json and deploys it through the general multi-step workflow deploy path. Returns the deployment record.

Body: unknown

201: unknown -- Workflow deployed 404: ErrorResponse -- Workflow asset not found 409: ErrorResponse -- Workflow definition could not be hydrated 500: ErrorResponse -- Deployment projection row missing after deploy 502: ErrorResponse -- Sidecar unavailable

GET /api/tenants/:tenantId/workflows/instances

List workflow deployments

Lists the workflow deployments for the tenant, most recent first.

200: unknown -- List of workflow deployments

POST /api/tenants/:tenantId/workflows/:deploymentId/signals

Deliver a signal to a workflow run

Delivers a caller-supplied, stable signal to the named run of a workflow deployment. The signalId must be supplied by the caller; the run state machine dedups on it.

Body: unknown

202: (no content) -- Signal accepted for delivery 404: ErrorResponse -- Workflow deployment not found 502: ErrorResponse -- Sidecar unavailable

POST /api/tenants/:tenantId/workflows/:deploymentId/mail

Trigger a workflow run

Assembles a fresh signed conversation message and delivers it to the deployment's inbound mail address, starting a new workflow run. The run id is minted by the supervisor and is not returned synchronously; correlate the resulting RunStarted via the returned messageId.

Body: SendMessage

202: unknown -- Trigger accepted for delivery 400: ErrorResponse -- Attachment validation error. Each variant carries a structured code (oversize_attachment, disallowed_mime_type, malformed_base64, oversize_total) with the offending index and limits. A malformed request body that fails SendMessage validation returns the generic error shape instead. 404: ErrorResponse -- Workflow deployment not found 409: ErrorResponse -- Deployment address is not routable 413: ErrorResponse -- Request body exceeds the maximum allowed size

GET /api/tenants/:tenantId/workflows/:deploymentId/runs

List workflow runs

Lists the run ids present in the deployment's workflow-run event log. Returns an empty list when no run has committed events yet.

200: unknown -- List of run ids 404: ErrorResponse -- Workflow deployment not found

GET /api/tenants/:tenantId/workflows/:deploymentId/runs/:runId/events

Read a workflow run's event log

Returns the seq-ordered event projection (RunStarted, StepStarted, StepCompleted, SignalAwaited, RunCompleted, etc.) for a single run. The full event log is returned in ascending seq order; an unknown run returns an empty list.

200: unknown -- Seq-ordered run events 404: ErrorResponse -- Workflow deployment not found

Approvals

GET /api/tenants/:tenantId/approvals

List pending approvals in the tenant

Returns pending approval requests for the authenticated user within this tenant.

200: ApprovalResponse[] -- List of approvals

GET /api/tenants/:tenantId/approvals/:approvalId

Get approval details

Returns the proposed action, context, originating agent, and session.

200: ApprovalResponse -- Approval details 404: ErrorResponse -- Approval not found

POST /api/tenants/:tenantId/approvals/:approvalId/approve

Approve an action

Approves the pending action. With scope 'once', the approval is one-time. Scope 'always' is not yet supported: a standing grant requires the tool identity, which the suspend path does not yet capture.

Body: ApproveAction

200: ApprovalResponse -- Action approved 400: ErrorResponse -- Unsupported scope 403: ErrorResponse -- Approver lacks the approval resolve grant 404: ErrorResponse -- Approval not found 409: ErrorResponse -- Approval already resolved

POST /api/tenants/:tenantId/approvals/:approvalId/reject

Reject an action

Rejects the pending action. An optional message provides feedback to the agent.

Body: RejectAction

200: ApprovalResponse -- Action rejected 403: ErrorResponse -- Approver lacks the approval resolve grant 404: ErrorResponse -- Approval not found 409: ErrorResponse -- Approval already resolved

Wallets

GET /api/tenants/:tenantId/wallets

List wallets in the tenant

Query: cursor?, limit?

200: unknown -- List of wallets

POST /api/tenants/:tenantId/wallets

Create a wallet

Creates a wallet with the specified payment backend and currency. Access for agents is managed through grants.

Body: CreateWallet

201: WalletResponse -- Wallet created 400: ErrorResponse -- Validation error

GET /api/tenants/:tenantId/wallets/:walletId

Get wallet details

Returns wallet details including current balance.

200: WalletResponse -- Wallet details 404: ErrorResponse -- Wallet not found

PATCH /api/tenants/:tenantId/wallets/:walletId

Update wallet config

Body: UpdateWallet

200: WalletResponse -- Wallet updated 404: ErrorResponse -- Wallet not found

DELETE /api/tenants/:tenantId/wallets/:walletId

Deactivate a wallet

204: (no content) -- Wallet deactivated 404: ErrorResponse -- Wallet not found

GET /api/tenants/:tenantId/wallets/:walletId/transactions

List transactions

Transaction history for a wallet. Filterable by agent, date range, and status.

Query: agentId?, startTime?, endTime?, status?: pending|completed|failed, cursor?, limit?

200: unknown -- List of transactions

Providers

GET /api/tenants/:tenantId/providers

List providers

Lists provider definitions for the tenant, including those inherited from ancestor tenants.

Query: inherited?: true|false, cursor?, limit?

200: unknown -- List of providers

POST /api/tenants/:tenantId/providers

Create a provider definition

Defines a new service provider for the tenant. The plugin field determines how Interchange integrates with the service.

Body: CreateProvider

201: ProviderResponse -- Provider created 400: ErrorResponse -- Validation error 409: ErrorResponse -- Provider name already exists in this tenant

GET /api/tenants/:tenantId/providers/:providerId

Get provider details

200: ProviderResponse -- Provider details 404: ErrorResponse -- Provider not found

PATCH /api/tenants/:tenantId/providers/:providerId

Update a provider definition

Only providers owned by this tenant can be updated.

Body: UpdateProvider

200: ProviderResponse -- Provider updated 404: ErrorResponse -- Provider not found

DELETE /api/tenants/:tenantId/providers/:providerId

Remove a provider definition

Only providers owned by this tenant can be removed.

204: (no content) -- Provider removed 404: ErrorResponse -- Provider not found

OAuth Clients

GET /api/tenants/:tenantId/oauth-clients

List OAuth client registrations

Lists OAuth client registrations for the tenant. Secrets are never returned.

Query: cursor?, limit?

200: unknown -- List of OAuth clients

POST /api/tenants/:tenantId/oauth-clients

Register an OAuth client

Registers an OAuth client (client_id/client_secret) for a provider. The provider must exist in the tenant or its ancestors.

Body: CreateOAuthClient

201: OAuthClientResponse -- OAuth client registered 400: ErrorResponse -- Validation error 404: ErrorResponse -- Provider not found 409: ErrorResponse -- OAuth client already exists for this provider in this tenant

GET /api/tenants/:tenantId/oauth-clients/:oauthClientId

Get OAuth client details

Returns OAuth client metadata. Secrets are never included.

200: OAuthClientResponse -- OAuth client details 404: ErrorResponse -- OAuth client not found

PATCH /api/tenants/:tenantId/oauth-clients/:oauthClientId

Update an OAuth client registration

Body: UpdateOAuthClient

200: OAuthClientResponse -- OAuth client updated 404: ErrorResponse -- OAuth client not found

DELETE /api/tenants/:tenantId/oauth-clients/:oauthClientId

Remove an OAuth client registration

204: (no content) -- OAuth client removed 404: ErrorResponse -- OAuth client not found

Credentials

GET /api/tenants/:tenantId/credentials

List credentials

Lists credential metadata. Secrets are never returned. Filterable by owner type.

Query: owner?: me|org|all, cursor?, limit?

200: unknown -- List of credentials

POST /api/tenants/:tenantId/credentials

Store a credential

Stores a credential (API key, OAuth token, etc.). The secret is stored securely and never returned in subsequent reads. A provider must be specified.

Body: CreateCredential

201: CredentialResponse -- Credential stored 400: ErrorResponse -- Validation error 404: ErrorResponse -- Provider not found 409: ErrorResponse -- Credential name already exists in this tenant

GET /api/tenants/:tenantId/credentials/resolve/:name

Resolve a credential by name

Resolves a credential by name, walking the tenant hierarchy. Returns metadata only (no secret). Useful for discovering which credential an agent would get.

200: CredentialResponse -- Credential metadata 404: ErrorResponse -- Credential not found

GET /api/tenants/:tenantId/credentials/:credentialId

Get credential metadata

Returns credential metadata. The secret is never included. Supports hierarchy-aware access.

200: CredentialResponse -- Credential metadata 404: ErrorResponse -- Credential not found

PATCH /api/tenants/:tenantId/credentials/:credentialId

Rotate or update a credential

Only credentials owned by this tenant can be updated.

Body: UpdateCredential

200: CredentialResponse -- Credential updated 404: ErrorResponse -- Credential not found

DELETE /api/tenants/:tenantId/credentials/:credentialId

Revoke a credential

Only credentials owned by this tenant can be revoked.

204: (no content) -- Credential revoked 404: ErrorResponse -- Credential not found

Discovery

GET /api/tenants/:tenantId/offerings

Search offerings

Searches offerings across discoverable agents in the tenant and federated tenants. Filterable by offering name, pricing range, and payment method.

Query: name?, minPrice?, maxPrice?, paymentMethod?, cursor?, limit?

200: unknown -- List of offerings

POST /api/tenants/:tenantId/offerings

Register an offering

Registers an offering for an agent. The agent must belong to the tenant.

Body: CreateOffering

201: OfferingDetail -- Offering registered 400: ErrorResponse -- Validation error 404: ErrorResponse -- Agent not found

GET /api/tenants/:tenantId/offerings/:offeringId

Get offering details

Returns pricing, agent info, and request/response type information.

200: OfferingDetail -- Offering details 404: ErrorResponse -- Offering not found

PATCH /api/tenants/:tenantId/offerings/:offeringId

Update an offering

Body: UpdateOffering

200: OfferingDetail -- Offering updated 404: ErrorResponse -- Offering not found

DELETE /api/tenants/:tenantId/offerings/:offeringId

Remove an offering

204: (no content) -- Offering removed 404: ErrorResponse -- Offering not found

GET /api/tenants/:tenantId/models

List the models resolved for the tenant

Returns the tenant's resolved catalog: every model visible after applying inheritance, shadowing, and disable suppression, broken down by the providers that offer it with each offering's active price per currency.

200: ModelInfo[] -- Resolved models

Catalog

GET /api/tenants/:tenantId/catalog/models

List models owned by the tenant

Lists the models created directly on this tenant. Models inherited from ancestor tenants are not included; use the model discovery endpoint to see the resolved catalog.

Query: cursor?, limit?

200: unknown -- List of models

POST /api/tenants/:tenantId/catalog/models

Create a model

Creates a tenant-local model. Reusing the canonical name of an inherited model shadows that model for this tenant and its descendants.

Body: CreateModel

201: ModelResponse -- Model created 409: ErrorResponse -- A model with this canonical name already exists

GET /api/tenants/:tenantId/catalog/models/:modelId

Get a model

200: ModelResponse -- Model details 404: ErrorResponse -- Model not found

PATCH /api/tenants/:tenantId/catalog/models/:modelId

Update a model

Body: UpdateModel

200: ModelResponse -- Model updated 404: ErrorResponse -- Model not found

DELETE /api/tenants/:tenantId/catalog/models/:modelId

Delete a model

Removes the model and cascades to the offerings that reference it. Running instances resolved through those offerings fail over to the next eligible source.

204: (no content) -- Model removed 404: ErrorResponse -- Model not found

GET /api/tenants/:tenantId/catalog/providers

List model providers owned by the tenant

Lists the model providers created directly on this tenant. Providers inherited from ancestor tenants are not included.

Query: cursor?, limit?

200: unknown -- List of model providers

POST /api/tenants/:tenantId/catalog/providers

Create a model provider

Registers an inference endpoint authenticated by exactly one of a credential or a wallet. Supplying both or neither is rejected.

Body: CreateModelProvider

201: ModelProviderResponse -- Provider created 400: ErrorResponse -- Exactly one of credentialId or walletId is required 404: ErrorResponse -- Credential not found in this tenant 409: ErrorResponse -- Provider name already exists in this tenant

GET /api/tenants/:tenantId/catalog/providers/:providerId

Get a model provider

200: ModelProviderResponse -- Provider details 404: ErrorResponse -- Provider not found

PATCH /api/tenants/:tenantId/catalog/providers/:providerId

Update a model provider

Updates a provider's name, base URL, or disabled flag. Changing the authentication binding is not supported; delete and recreate the provider to repoint it.

Body: UpdateModelProvider

200: ModelProviderResponse -- Provider updated 404: ErrorResponse -- Provider not found 409: ErrorResponse -- Provider name already exists in this tenant

DELETE /api/tenants/:tenantId/catalog/providers/:providerId

Delete a model provider

Removes the provider and cascades to the offerings that reference it. Running instances resolved through those offerings fail over to the next eligible source.

204: (no content) -- Provider removed 404: ErrorResponse -- Provider not found

GET /api/tenants/:tenantId/catalog/offerings

List model offerings owned by the tenant

Lists the model offerings created directly on this tenant. Offerings inherited from ancestor tenants are not included; use the model discovery endpoint to see the resolved catalog.

Query: cursor?, limit?

200: unknown -- List of model offerings

POST /api/tenants/:tenantId/catalog/offerings

Create a model offering

Pairs a tenant-owned model with a tenant-owned provider. To offer an inherited model or provider, first create a tenant-local copy of it (shadowing).

Body: CreateModelOffering

201: ModelOfferingResponse -- Offering created 404: ErrorResponse -- Model or provider not found in this tenant 409: ErrorResponse -- Offering already exists for this model and provider

GET /api/tenants/:tenantId/catalog/offerings/:offeringId

Get a model offering

200: ModelOfferingResponse -- Offering details 404: ErrorResponse -- Offering not found

PATCH /api/tenants/:tenantId/catalog/offerings/:offeringId

Update a model offering

Body: UpdateModelOffering

200: ModelOfferingResponse -- Offering updated 404: ErrorResponse -- Offering not found

DELETE /api/tenants/:tenantId/catalog/offerings/:offeringId

Delete a model offering

Removes the offering and its pricing history. Running instances resolved through it fail over to the next eligible source.

204: (no content) -- Offering removed 404: ErrorResponse -- Offering not found

GET /api/tenants/:tenantId/catalog/offerings/:offeringId/pricing

List an offering's pricing history

Returns the full append-only pricing history for an offering, every currency and effective-from date, newest first.

200: PricingRowResponse[] -- Pricing rows 404: ErrorResponse -- Offering not found

POST /api/tenants/:tenantId/catalog/offerings/:offeringId/pricing

Add a pricing row to an offering

Appends a pricing row. Pricing is append-only: a price change inserts a new row with a later effective-from rather than editing an existing one, so historical cost attribution stays accurate.

Body: CreatePricingRow

201: PricingRowResponse -- Pricing row created 400: ErrorResponse -- effectiveFrom is not a valid timestamp 404: ErrorResponse -- Offering not found 409: ErrorResponse -- A pricing row already exists for this currency and effective-from

Observability

GET /api/tenants/:tenantId/agents/:agentId/logs

Get agent logs

Structured logs for an agent. Filterable by level and time range.

Query: level?: debug|info|warn|error, startTime?, endTime?

200: LogEntry[] -- Log entries 404: ErrorResponse -- Agent not found

GET /api/tenants/:tenantId/agents/:agentId/metrics

Get agent metrics

Returns throughput, latency, error rates, token usage, and cost metrics.

200: MetricsResponse -- Agent metrics 404: ErrorResponse -- Agent not found

GET /api/tenants/:tenantId/traces

Query distributed traces

Searches traces within the tenant. Filterable by agent, session, time range, and trace ID.

Query: agentId?, sessionId?, traceId?, startTime?, endTime?

200: SpanResponse[] -- List of traces

GET /api/tenants/:tenantId/traces/:traceId

Get a full trace

Returns all spans in a trace across agent boundaries.

200: TraceResponse -- Trace with spans 404: ErrorResponse -- Trace not found

Agent Data

GET /api/tenants/:tenantId/agents/:agentId/data

List files in agent working directory

200: FileEntry[] -- File listing 404: ErrorResponse -- Agent not found

GET /api/tenants/:tenantId/agents/:agentId/data/*

Read a file from agent storage

Reads a file by path from the agent's local storage.

200: FileContent -- File content 404: ErrorResponse -- File or agent not found

GET /api/tenants/:tenantId/agents/:agentId/history

List commits and checkpoints

Returns the agent's change history with commit messages and timestamps.

200: HistoryEntry[] -- History entries

GET /api/tenants/:tenantId/agents/:agentId/history/:ref

Show changes in a commit

Returns the files changed in a specific commit with additions/deletions counts.

200: CommitDetail -- Commit details 404: ErrorResponse -- Commit not found

GET /api/tenants/:tenantId/agents/:agentId/branches

List branches

Lists branches in the agent's data repository.

200: BranchInfo[] -- List of branches

POST /api/tenants/:tenantId/agents/:agentId/history/:ref/restore

Restore agent data to a previous state

Restores the agent's working directory to the state at the specified commit.

204: (no content) -- Data restored 404: ErrorResponse -- Commit not found

Assets

GET /api/tenants/:tenantId/assets

List assets

Lists assets for the tenant. With inherited=true (the default), assets defined on ancestor tenants are included; descendant tenants shadow ancestors when they declare the same (kind, name) pair. Each row carries an origin tag identifying the tenant that supplied it.

Query: kind?, inherited?: true|false

200: AssetWithOriginResponse[] -- List of assets

POST /api/tenants/:tenantId/assets

Create an asset

Inserts an asset row and initializes the backing git repository with a hub-signed genesis commit and the asset-route .gitignore body.

Body: unknown

201: unknown -- Asset created 400: ErrorResponse -- Validation error 409: ErrorResponse -- Asset already exists

GET /api/tenants/:tenantId/assets/:assetId

Get asset metadata

Returns asset metadata. Resolves through the tenant hierarchy: assets declared on the tenant or any ancestor are visible. Sibling-tenant assets return 404 so callers cannot probe for cross-tenant existence.

200: AssetResponse -- Asset metadata 404: ErrorResponse -- Asset not found

PUT /api/tenants/:tenantId/assets/:assetId/tarballs/:filename

Upload a tarball into a package-registry asset

Commits raw tarball bytes at tarballs/ in the package-registry asset's git tree. Overwrites permitted. The kind handler validates the tarball's package.json before the commit is accepted.

200: unknown -- Tarball stored 400: ErrorResponse -- Invalid filename or rejected content 404: ErrorResponse -- Asset not found

DELETE /api/tenants/:tenantId/assets/:assetId/tarballs/:filename

Delete a tarball from a package-registry asset

Removes the named tarball from the package-registry asset and commits the resulting tree. Returns 404 if the asset or filename does not exist.

200: unknown -- Tarball removed 400: ErrorResponse -- Invalid filename 404: ErrorResponse -- Asset or filename not found

GET /api/tenants/:tenantId/assets/:assetId/tarballs

List tarballs in a package-registry asset

Returns the current set of tarballs under tarballs/ for the package-registry asset, with size and SRI integrity for each entry.

200: unknown -- Tarball list 404: ErrorResponse -- Asset not found

Type Reference

AgentHealth

{ liveness: "ok" | "unhealthy", readiness: "not_ready" | "ok" | "unhealthy", lastCheckedAt?: string | null } Source: packages/types/src/agents.ts

AgentInstanceResponse

{ address: string, agentId: string, agentName: string, createdAt: string, id: string, status: "deployed" | "error" | "running" | "stopped" | "updating", tenantId: string, updatedAt: string, endedAt?: string | null, kernelId?: string | null, publicKey?: string | null, sidecarId?: string | null } Source: packages/types/src/agents.ts

status: Lifecycle state of this running instance: deployed (provisioned on a sidecar, not yet started), running (started and serving), updating (rolling to a new definition version), error (launch or runtime failure), or stopped (undeployed).

AgentResponse

{ createdAt: string, creatorPrincipalId: string, currentVersion: string, id: string, name: string, status: "deployed" | "stopped", tenantId: string, toolPackages: { name: /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/, version: string }[], updatedAt: string, capabilities?: { [string]: unknown }, contextConfig?: { [string]: unknown }, credentialRequirements?: { providerName: string, source: "creator" | "invoker" | "tenant", name?: string, scopes?: string[] }[], description?: string | null, grantRequirements?: { action: string, resource: string, source: "creator" | "invoker", conditions?: { [string]: unknown } | null, effect?: "allow" | "ask" | "deny" }[], initialState?: { [string]: unknown }, modelConfig?: { [string]: unknown }, modelRequirements?: { model: string, capabilities?: ("audio-input" | "extended-thinking" | "long-context" | "prompt-caching" | "structured-output" | "tool-use" | "vision")[], providers?: { mode: "pin" | "prefer", order: string[] } }[], roles?: { id: string, name: string }[], systemPrompt?: string | null } Source: packages/types/src/agents.ts

creatorPrincipalId: Identifies the definition author's principal (definitions have no principalId of their own). Used for resolving creator-sourced grant and credential requirements. status: Lifecycle state of the agent definition: deployed (a launchable version is active) or stopped (deactivated, no new instances launch). toolPackages: Tool packages this definition pins. Always present; an empty array means the definition pins no packages (the agent runs with whatever non-tool-package factories the sidecar harness ships). modelRequirements: Model needs declared by canonical name, with optional per-model capability filters and provider preferences. Resolved against the tenant catalog at launch to build the ordered inference sources; it does not introduce providers the tenant catalog lacks.

ApprovalResponse

{ agentAddress: string, correlationId: string, createdAt: string, deploymentId: string, id: string, resolvedAt: string | null, runId: string, scope: "always" | "once" | null, status: "approved" | "expired" | "pending" | "rejected" | "timeout", tenantId: string, timeoutAt: string | null, toolArguments: { [string]: unknown } | null, toolDefinition: { [string]: unknown } | null, updatedAt: string } Source: packages/types/src/approvals.ts

correlationId: Ties the approval to the suspension it resolves. The parked run awaits the control signal keyed by this id. deploymentId: The workflow deployment the approval originates from. Every approval is raised during a workflow run; there is no launched single agent or agent-definition row behind it. timeoutAt: Deadline after which the approval expires. Null records a hold-indefinitely approval with no deadline. toolDefinition: The approver-facing tool snapshot. Null until the inference-layer plumbing that captures it at suspend time is in place.

ApprovalSummary

{ action: string, agentId: string, agentName: string, createdAt: string, id: string, resource: string, sessionId: string, tenantId: string, tenantName: string } Source: packages/types/src/me.ts

sessionId: Internal FK to the session channel. The instance ID can be resolved via the session relationship.

ApproveAction

{ scope: "always" | "once" } Source: packages/types/src/approvals.ts

AssetResponse

{ createdAt: string, creatorPrincipalId: string | null, displayName: string | null, id: string, kind: string, name: string, tenantId: string, updatedAt: string } Source: packages/types/src/assets.ts

kind: Category of the asset, used together with name to address it. The (kind, name) pair is what callers resolve against, and it is unique within a tenant.

AssetWithOriginResponse

{ createdAt: string, creatorPrincipalId: string | null, displayName: string | null, id: string, kind: string, name: string, origin: { direct: boolean, tenantId: string }, tenantId: string, updatedAt: string } Source: packages/types/src/assets.ts

kind: Category of the asset, used together with name to address it. The (kind, name) pair is what callers resolve against, and it is unique within a tenant. origin: Which tenant in the hierarchy this asset row came from, distinguishing locally-defined assets from inherited ones.

AttachmentErrorResponse

{ error: { attachmentIndex: number, byteLength: number, code: "oversize_attachment", limitBytes: number, message: string } | { attachmentIndex: number, code: "disallowed_mime_type", message: string, mimeType: string } | { attachmentIndex: number, code: "invalid_attachment_name", message: string } | { attachmentIndex: number, code: "malformed_base64", message: string } | { code: "oversize_total", limitBytes: number, message: string, totalBytes: number } } Source: packages/types/src/sessions.ts

BranchInfo

{ name: string, isCurrent?: boolean, lastCommitAt?: string | null, lastCommitMessage?: string | null, lastCommitRef?: string | null } Source: packages/types/src/agent-data.ts

CommitDetail

{ author: string, changes: { path: string, status: "added" | "deleted" | "modified", additions?: number, deletions?: number }[], message: string, ref: string, timestamp: string } Source: packages/types/src/agent-data.ts

CreateAgent

{ name: string, capabilities?: { [string]: unknown }, contextConfig?: { [string]: unknown }, credentialRequirements?: { providerName: string, source: "creator" | "invoker" | "tenant", name?: string, scopes?: string[] }[], description?: string, grantRequirements?: { action: string, resource: string, source: "creator" | "invoker", conditions?: { [string]: unknown } | null, effect?: "allow" | "ask" | "deny" }[], initialState?: { [string]: unknown }, modelConfig?: { [string]: unknown }, modelRequirements?: { model: string, capabilities?: ("audio-input" | "extended-thinking" | "long-context" | "prompt-caching" | "structured-output" | "tool-use" | "vision")[], providers?: { mode: "pin" | "prefer", order: string[] } }[], roleIds?: string[], systemPrompt?: string, toolPackages?: { name: /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/, version: string }[] } Source: packages/types/src/agents.ts

grantRequirements: A grant requirements manifest, not live grants. Each entry declares a resource, action, and source (creator or invoker). The control plane resolves these requirements at each agent launch against the current authority of the creator and invoker. modelRequirements: Model needs declared by canonical name, with optional per-model capability filters and provider preferences. Resolved against the tenant catalog at launch to build the ordered inference sources; it does not introduce providers the tenant catalog lacks. toolPackages: Tool packages pinned by this agent definition. Each entry must use a valid npm package name (lowercase, optionally @scope/-prefixed) and a parseable semver range; the array must contain no duplicate names. The hub resolves the full dependency closure at deploy-assembly time and ships the manifest to the sidecar; the sidecar materializes each pinned package and registers its tools with the harness.

CreateAgentInstance

{ agentId: string, invokerGrants?: { action: string, resource: string, conditions?: { [string]: unknown } | null, effect?: "allow" | "ask" | "deny" }[], modelPreferences?: { model: string, providers: { mode: "pin" | "prefer", order: string[] } }[] } Source: packages/types/src/agents.ts

invokerGrants: Capabilities the invoker is willing to delegate to the agent, resolved against the invoker's own authority at launch. These are materialized as grants on the agent principal in addition to any grants from the definition's own requirements. modelPreferences: The invoker's per-model provider preferences for this launch. Applied over the tenant-visible providers after the definition's preferences; it can only reorder or restrict, never introduce a provider the tenant catalog lacks. Persisted on the instance so re-resolution reuses it.

CreateCredential

{ name: string, providerId: string, secret: string, type: "api_key" | "certificate" | "oauth_token" | "other", description?: string, expiresAt?: string, metadata?: { [string]: unknown }, oauthClientId?: string, principalId?: string, refreshSecret?: string, scopes?: string[] } Source: packages/types/src/credentials.ts

type: Kind of secret material this credential holds: api_key, oauth_token, certificate, or other. Determines how secret (and refreshSecret for OAuth) is interpreted when the credential is used. metadata: Free-form provider- or integration-specific data attached to the credential. Not interpreted by the hub. scopes: Permissions granted to this credential by the provider (for example OAuth scopes). Informational on the credential record; the provider is the authority on what the secret can actually do.

CreateFederationTrust

{ direction: "bilateral" | "inbound" | "outbound", targetTenantId: string } Source: packages/types/src/tenants.ts

CreateGrant

{ action: string, effect: "allow" | "ask" | "deny", origin: "creator" | "invoker" | "role" | "system", resource: string, conditions?: { [string]: unknown } | null, expiresAt?: string | null, principalId?: string | null, roleId?: string | null } Source: packages/types/src/grants.ts

effect: Outcome when this grant is the one resolved for a request: allow permits the action, deny blocks it, ask requires interactive approval before proceeding. When several grants match, the most specific wins, and at equal specificity the strongest effect wins (deny over ask over allow). origin: Records where the grant came from: system (built-in), role (granted via a role), creator (from the agent definition author), or invoker (delegated by whoever launched the agent). Origin is provenance only; it does not affect evaluation precedence. conditions: Optional map of named conditions that must all pass for the grant to apply, evaluated against a condition registry at authorization time. A grant with conditions is skipped (fails closed) when no registry is available to evaluate them.

CreateModel

{ canonicalName: string, description?: string | null, displayName?: string | null } Source: packages/types/src/catalog.ts

canonicalName: Tenant-unique canonical model name agents match their requirements against.

CreateModelOffering

{ modelId: string, providerId: string, capabilities?: ("audio-input" | "extended-thinking" | "long-context" | "prompt-caching" | "structured-output" | "tool-use" | "vision")[], deploymentTags?: string[], priority?: number } Source: packages/types/src/catalog.ts

modelId: Catalog id of a model owned by this tenant. providerId: Catalog id of a model-provider owned by this tenant. priority: Ordering hint for source resolution; lower values are preferred first. Defaults to 0.

CreateModelProvider

{ baseURL: string, name: string, plugin: "anthropic" | "google-genai" | "openai" | "openai-compatible", credentialId?: string | null, walletId?: string | null } Source: packages/types/src/catalog.ts

name: Tenant-unique model-provider name. plugin: The inference adapter that serves this provider's models, dispatched by the runtime provider registry.

CreateOAuthClient

{ clientId: string, clientSecret: string, name: string, providerId: string, defaultScopes?: string[], metadata?: { [string]: unknown }, redirectUris?: string[] } Source: packages/types/src/oauth-clients.ts

defaultScopes: Scopes requested by default when initiating an authorization flow with this client. metadata: Free-form client-specific configuration not covered by the typed fields. Not interpreted by the hub. redirectUris: Allowed OAuth redirect URIs for this client. The authorization callback must match one of these.

CreateOffering

{ agentId: string, name: string, description?: string, pricing?: { base?: { amount: string, currency: string }, bounds?: { max?: string, min?: string }, methods?: string[], negotiable?: boolean }, schema?: { [string]: unknown } } Source: packages/types/src/offerings.ts

CreatePricingRow

{ currency: string, cacheReadTokenPrice?: string | null, cacheWriteTokenPrice?: string | null, effectiveFrom?: string, inputTokenPrice?: string | null, outputTokenPrice?: string | null, perAudioFee?: string | null, perImageFee?: string | null, perRequestFee?: string | null, thinkingTokenPrice?: string | null } Source: packages/types/src/catalog.ts

currency: Fiat currency code or opaque credit unit this row prices in. cacheReadTokenPrice: Cost per cached-read token as a decimal string in this row's currency, or null if this provider does not charge for it. cacheWriteTokenPrice: Cost per cached-write token as a decimal string in this row's currency, or null if this provider does not charge for it. effectiveFrom: ISO-8601 timestamp from which this price applies. Defaults to the time of the request. inputTokenPrice: Cost per input token as a decimal string in this row's currency, or null if this provider does not charge for it. outputTokenPrice: Cost per output token as a decimal string in this row's currency, or null if this provider does not charge for it. perAudioFee: Fee per audio unit as a decimal string in this row's currency, or null if this provider does not charge for it. perImageFee: Fee per image as a decimal string in this row's currency, or null if this provider does not charge for it. perRequestFee: Flat fee per request as a decimal string in this row's currency, or null if this provider does not charge for it. thinkingTokenPrice: Cost per thinking token as a decimal string in this row's currency, or null if this provider does not charge for it.

CreateProvider

{ name: string, plugin: string, authorizationUrl?: string, metadata?: { [string]: unknown }, scopes?: string[], tokenUrl?: string, userInfoUrl?: string } Source: packages/types/src/providers.ts

plugin: Identifier of the integration this provider drives (for example the inference backend). Used to dispatch to the matching plugin and as the prefix when forming fully-qualified model ids (plugin:model). metadata: Free-form provider-specific configuration not covered by the typed fields. Not interpreted by the hub. scopes: OAuth scopes associated with this provider integration.

CreateRole

{ name: string, description?: string } Source: packages/types/src/roles.ts

CreateTenant

{ name: string, slug: string, parentId?: string | null } Source: packages/types/src/tenants.ts

CreateWallet

{ backendType: "credits" | "crypto" | "fiat", currency: string, name: string, config?: { [string]: unknown } } Source: packages/types/src/wallets.ts

backendType: Settlement backend the wallet is denominated in: crypto (on-chain assets), fiat (national currency), or credits (internal accounting units). Determines how balances and transactions are settled. config: Backend-specific configuration for the wallet (for example chain or account details for a crypto backend). Shape depends on backendType; not interpreted by the hub.

CredentialResponse

{ createdAt: string, id: string, name: string, providerId: string, status: "active" | "error" | "expired" | "revoked", tenantId: string, type: "api_key" | "certificate" | "oauth_token" | "other", updatedAt: string, description?: string | null, expiresAt?: string | null, metadata?: { [string]: unknown } | null, oauthClientId?: string | null, principalId?: string | null, scopes?: string[] | null } Source: packages/types/src/credentials.ts

status: Usability state of the credential: active (usable), expired (past its expiresAt), revoked (deliberately invalidated), or error (last use failed, e.g. rejected by the provider). type: Kind of secret material this credential holds: api_key, oauth_token, certificate, or other. Determines how secret (and refreshSecret for OAuth) is interpreted when the credential is used. metadata: Free-form provider- or integration-specific data attached to the credential. Not interpreted by the hub. scopes: Permissions granted to this credential by the provider (for example OAuth scopes). Informational on the credential record; the provider is the authority on what the secret can actually do.

ErrorResponse

{ error: { code: string, message: string } } Source: packages/types/src/common.ts

EvaluateRequest

{ action: string, resource: string } Source: packages/types/src/grants.ts

EvaluateResult

{ effect: "allow" | "ask" | "deny", matchingGrants: { action: string, effect: "allow" | "ask" | "deny", id: string, origin: "creator" | "invoker" | "role" | "system", resource: string, specificity?: number }[] } Source: packages/types/src/grants.ts

effect: The resolved outcome for the query: the effect of the winning grant, or deny when no grant matched (authorization fails closed). matchingGrants: Every grant that matched the requested resource and action, including the one that won. Useful for debugging why a request was allowed, denied, or required approval.

FederationTrust

{ createdAt: string, direction: "bilateral" | "inbound" | "outbound", tenantDomain: string, tenantId: string, tenantName: string } Source: packages/types/src/tenants.ts

FileContent

{ content: string, path: string, encoding?: "base64" | "utf-8" } Source: packages/types/src/agent-data.ts

FileEntry

{ path: string, type: "directory" | "file", modifiedAt?: string | null, size?: number | null } Source: packages/types/src/agent-data.ts

GrantResponse

{ action: string, createdAt: string, effect: "allow" | "ask" | "deny", id: string, origin: "creator" | "invoker" | "role" | "system", resource: string, tenantId: string, updatedAt: string, conditions?: { [string]: unknown } | null, expiresAt?: string | null, principalId?: string | null, principalName?: string | null, roleId?: string | null, roleName?: string | null } Source: packages/types/src/grants.ts

effect: Outcome when this grant is the one resolved for a request: allow permits the action, deny blocks it, ask requires interactive approval before proceeding. When several grants match, the most specific wins, and at equal specificity the strongest effect wins (deny over ask over allow). origin: Records where the grant came from: system (built-in), role (granted via a role), creator (from the agent definition author), or invoker (delegated by whoever launched the agent). Origin is provenance only; it does not affect evaluation precedence. conditions: Optional map of named conditions that must all pass for the grant to apply, evaluated against a condition registry at authorization time. A grant with conditions is skipped (fails closed) when no registry is available to evaluate them.

HistoryEntry

{ author: string, message: string, ref: string, timestamp: string, filesChanged?: number } Source: packages/types/src/agent-data.ts

InviteMember

{ email: string, roleId?: string } Source: packages/types/src/principals.ts

LogEntry

{ level: "debug" | "error" | "info" | "warn", message: string, timestamp: string, metadata?: { [string]: unknown } | null } Source: packages/types/src/observability.ts

MailResponse

{ attachments: { blobId: string, name: string | null, size: number, type: string }[], bodyValues: { [string]: unknown }, direction: "inbound" | "outbound", from: { email: string, name: string | null }[], headers: { [string]: string }, htmlBody: { partId: string, type: string }[], id: string, instanceId: string | null, receivedAt: string, sentAt: string | null, sessionId: string, status: "delivered" | "pending", subject: string | null, textBody: { partId: string, type: string }[], to: { email: string, name: string | null }[] } Source: packages/types/src/sessions.ts

direction: Whether the message was sent to the agent (inbound) or emitted by the agent (outbound). sessionId: Internal session channel identifier, not a user-facing session resource. status: Delivery state of the mail: pending (accepted, not yet dispatched to the running agent) or delivered.

MetricsResponse

{ agentId: string, avgLatencyMs?: number, cost?: string, errorRate?: number, messageCount?: number, tokenUsage?: { input?: number, output?: number, total?: number } } Source: packages/types/src/observability.ts

ModelInfo

{ canonicalName: string, id: string, offerings: { capabilities: ("audio-input" | "extended-thinking" | "long-context" | "prompt-caching" | "structured-output" | "tool-use" | "vision")[], deploymentTags: string[], offeringId: string, plugin: "anthropic" | "google-genai" | "openai" | "openai-compatible", pricing: { createdAt: string, currency: string, effectiveFrom: string, id: string, offeringId: string, tenantId: string, cacheReadTokenPrice?: string | null, cacheWriteTokenPrice?: string | null, inputTokenPrice?: string | null, outputTokenPrice?: string | null, perAudioFee?: string | null, perImageFee?: string | null, perRequestFee?: string | null, thinkingTokenPrice?: string | null }[], priority: number, providerId: string, providerName: string }[], description?: string | null, displayName?: string | null } Source: packages/types/src/models.ts

canonicalName: The model's tenant-unique canonical name, matched against an agent's model requirements. offerings: One entry per provider that offers this model in the tenant's resolved catalog, ordered by resolution priority.

ModelOfferingResponse

{ capabilities: ("audio-input" | "extended-thinking" | "long-context" | "prompt-caching" | "structured-output" | "tool-use" | "vision")[], createdAt: string, deploymentTags: string[], disabled: boolean, id: string, modelId: string, priority: number, providerId: string, tenantId: string, updatedAt: string } Source: packages/types/src/catalog.ts

capabilities: Curated capability tags this provider advertises for this model. priority: Ordering hint for source resolution; lower values are preferred first.

ModelProviderResponse

{ baseURL: string, createdAt: string, disabled: boolean, id: string, name: string, plugin: "anthropic" | "google-genai" | "openai" | "openai-compatible", tenantId: string, updatedAt: string, credentialId?: string | null, walletId?: string | null } Source: packages/types/src/catalog.ts

plugin: The inference adapter that serves this provider's models, dispatched by the runtime provider registry.

ModelResponse

{ canonicalName: string, createdAt: string, disabled: boolean, id: string, tenantId: string, updatedAt: string, description?: string | null, displayName?: string | null } Source: packages/types/src/catalog.ts

OAuthClientResponse

{ createdAt: string, id: string, name: string, providerId: string, tenantId: string, updatedAt: string, defaultScopes?: string[] | null, metadata?: { [string]: unknown } | null, redirectUris?: string[] | null } Source: packages/types/src/oauth-clients.ts

defaultScopes: Scopes requested by default when initiating an authorization flow with this client. metadata: Free-form client-specific configuration not covered by the typed fields. Not interpreted by the hub. redirectUris: Allowed OAuth redirect URIs for this client. The authorization callback must match one of these.

OfferingDetail

{ agentId: string, agentName: string, id: string, name: string, tenantId: string, description?: string | null, pricing?: { base?: { amount: string, currency: string }, bounds?: { max?: string, min?: string }, methods?: string[], negotiable?: boolean }, schema?: { [string]: unknown } | null } Source: packages/types/src/offerings.ts

PricingRowResponse

{ createdAt: string, currency: string, effectiveFrom: string, id: string, offeringId: string, tenantId: string, cacheReadTokenPrice?: string | null, cacheWriteTokenPrice?: string | null, inputTokenPrice?: string | null, outputTokenPrice?: string | null, perAudioFee?: string | null, perImageFee?: string | null, perRequestFee?: string | null, thinkingTokenPrice?: string | null } Source: packages/types/src/catalog.ts

currency: Fiat currency code or opaque credit unit this row prices in. effectiveFrom: ISO-8601 timestamp from which this price applies. Cost attribution at a past time uses the latest row whose effectiveFrom is at or before that time. cacheReadTokenPrice: Cost per cached-read token as a decimal string in the row's currency, or null if this provider does not charge for it. cacheWriteTokenPrice: Cost per cached-write token as a decimal string in the row's currency, or null if this provider does not charge for it. inputTokenPrice: Cost per input token as a decimal string in the row's currency, or null if this provider does not charge for it. outputTokenPrice: Cost per output token as a decimal string in the row's currency, or null if this provider does not charge for it. perAudioFee: Fee per audio unit as a decimal string in the row's currency, or null if this provider does not charge for it. perImageFee: Fee per image as a decimal string in the row's currency, or null if this provider does not charge for it. perRequestFee: Flat fee per request as a decimal string in the row's currency, or null if this provider does not charge for it. thinkingTokenPrice: Cost per thinking token as a decimal string in the row's currency, or null if this provider does not charge for it.

PrincipalResponse

{ createdAt: string, displayName: string, id: string, kind: "agent" | "user", refId: string, roles: { id: string, name: string }[], status: "active" | "deactivated" | "invited" | "suspended", tenantId: string, updatedAt: string, email?: string } Source: packages/types/src/principals.ts

kind: Whether this principal represents a user (a human account) or an agent. refId: Identifier of the underlying entity this principal stands for: the auth user id when kind is user, or the agent id when kind is agent. Unique per tenant and kind. status: Account state of the principal: active, suspended, invited (membership pending acceptance), or deactivated.

ProviderResponse

{ createdAt: string, id: string, name: string, plugin: string, tenantId: string, updatedAt: string, authorizationUrl?: string | null, metadata?: { [string]: unknown } | null, scopes?: string[] | null, tokenUrl?: string | null, userInfoUrl?: string | null } Source: packages/types/src/providers.ts

plugin: Identifier of the integration this provider drives (for example the inference backend). Used to dispatch to the matching plugin and as the prefix when forming fully-qualified model ids (plugin:model). metadata: Free-form provider-specific configuration not covered by the typed fields. Not interpreted by the hub. scopes: OAuth scopes associated with this provider integration.

RejectAction

{ message?: string } Source: packages/types/src/approvals.ts

RoleResponse

{ createdAt: string, id: string, isSystem: boolean, name: string, tenantId: string, updatedAt: string, description?: string | null } Source: packages/types/src/roles.ts

RollbackRequest

{ version: string } Source: packages/types/src/agents.ts

SendMessage

{ content: string, attachments?: { data: string, mimeType: string, name?: string, + (undeclared): reject }[] } Source: packages/types/src/sessions.ts

SessionSummary

{ agentId: string, agentName: string, createdAt: string, id: string, status: "ended" | "ending" | "idle", tenantId: string, tenantName: string, lastActivityAt?: string | null } Source: packages/types/src/me.ts

SpanResponse

{ name: string, spanId: string, startTime: string, traceId: string, agentId?: string | null, attributes?: { [string]: unknown } | null, durationMs?: number | null, endTime?: string | null, parentSpanId?: string | null, status?: "error" | "ok" } Source: packages/types/src/observability.ts

TenantResponse

{ createdAt: string, domain: string, id: string, name: string, slug: string, updatedAt: string, config?: { [string]: unknown }, parentId?: string | null } Source: packages/types/src/tenants.ts

TraceResponse

{ spans: { name: string, spanId: string, startTime: string, traceId: string, agentId?: string | null, attributes?: { [string]: unknown } | null, durationMs?: number | null, endTime?: string | null, parentSpanId?: string | null, status?: "error" | "ok" }[], traceId: string } Source: packages/types/src/observability.ts

UpdateAgent

{ capabilities?: { [string]: unknown }, contextConfig?: { [string]: unknown }, credentialRequirements?: { providerName: string, source: "creator" | "invoker" | "tenant", name?: string, scopes?: string[] }[], description?: string, grantRequirements?: { action: string, resource: string, source: "creator" | "invoker", conditions?: { [string]: unknown } | null, effect?: "allow" | "ask" | "deny" }[], initialState?: { [string]: unknown }, modelConfig?: { [string]: unknown }, modelRequirements?: { model: string, capabilities?: ("audio-input" | "extended-thinking" | "long-context" | "prompt-caching" | "structured-output" | "tool-use" | "vision")[], providers?: { mode: "pin" | "prefer", order: string[] } }[], name?: string, roleIds?: string[], systemPrompt?: string, toolPackages?: { name: /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/, version: string }[] } Source: packages/types/src/agents.ts

modelRequirements: Model needs declared by canonical name, with optional per-model capability filters and provider preferences. Resolved against the tenant catalog at launch to build the ordered inference sources; it does not introduce providers the tenant catalog lacks.

UpdateCredential

{ description?: string, expiresAt?: string | null, metadata?: { [string]: unknown }, name?: string, refreshSecret?: string | null, scopes?: string[] | null, secret?: string, status?: "active" | "error" | "expired" | "revoked" } Source: packages/types/src/credentials.ts

metadata: Free-form provider- or integration-specific data attached to the credential. Not interpreted by the hub. scopes: Permissions granted to this credential by the provider (for example OAuth scopes). Informational on the credential record; the provider is the authority on what the secret can actually do. status: Usability state of the credential: active (usable), expired (past its expiresAt), revoked (deliberately invalidated), or error (last use failed, e.g. rejected by the provider).

UpdateGrant

{ conditions?: { [string]: unknown } | null, effect?: "allow" | "ask" | "deny", expiresAt?: string | null } Source: packages/types/src/grants.ts

conditions: Optional map of named conditions that must all pass for the grant to apply, evaluated against a condition registry at authorization time. A grant with conditions is skipped (fails closed) when no registry is available to evaluate them. effect: Outcome when this grant is the one resolved for a request: allow permits the action, deny blocks it, ask requires interactive approval before proceeding. When several grants match, the most specific wins, and at equal specificity the strongest effect wins (deny over ask over allow).

UpdateModel

{ description?: string | null, disabled?: boolean, displayName?: string | null } Source: packages/types/src/catalog.ts

UpdateModelOffering

{ capabilities?: ("audio-input" | "extended-thinking" | "long-context" | "prompt-caching" | "structured-output" | "tool-use" | "vision")[], deploymentTags?: string[], disabled?: boolean, priority?: number } Source: packages/types/src/catalog.ts

UpdateModelProvider

{ baseURL?: string, disabled?: boolean, name?: string } Source: packages/types/src/catalog.ts

UpdateOAuthClient

{ clientId?: string, clientSecret?: string, defaultScopes?: string[] | null, metadata?: { [string]: unknown } | null, name?: string, redirectUris?: string[] | null } Source: packages/types/src/oauth-clients.ts

defaultScopes: Scopes requested by default when initiating an authorization flow with this client. metadata: Free-form client-specific configuration not covered by the typed fields. Not interpreted by the hub. redirectUris: Allowed OAuth redirect URIs for this client. The authorization callback must match one of these.

UpdateOffering

{ description?: string, name?: string, pricing?: { base?: { amount: string, currency: string }, bounds?: { max?: string, min?: string }, methods?: string[], negotiable?: boolean }, schema?: { [string]: unknown } } Source: packages/types/src/offerings.ts

UpdatePrincipal

{ status: "active" | "deactivated" | "suspended" } Source: packages/types/src/principals.ts

status: New account state for the principal. Only active, suspended, and deactivated are settable; invited is reached only through the invitation flow.

UpdateProvider

{ authorizationUrl?: string | null, metadata?: { [string]: unknown } | null, name?: string, plugin?: string, scopes?: string[] | null, tokenUrl?: string | null, userInfoUrl?: string | null } Source: packages/types/src/providers.ts

metadata: Free-form provider-specific configuration not covered by the typed fields. Not interpreted by the hub. plugin: Identifier of the integration this provider drives (for example the inference backend). Used to dispatch to the matching plugin and as the prefix when forming fully-qualified model ids (plugin:model). scopes: OAuth scopes associated with this provider integration.

UpdateRole

{ description?: string, name?: string } Source: packages/types/src/roles.ts

UpdateTenant

{ config?: { [string]: unknown }, name?: string } Source: packages/types/src/tenants.ts

UpdateWallet

{ config?: { [string]: unknown }, name?: string } Source: packages/types/src/wallets.ts

config: Backend-specific configuration for the wallet (for example chain or account details for a crypto backend). Shape depends on backendType; not interpreted by the hub.

UserProfile

{ createdAt: string, email: string, emailVerified: boolean, id: string, name: string, updatedAt: string, image?: string | null } Source: packages/types/src/me.ts

WalletResponse

{ backendType: "credits" | "crypto" | "fiat", balance: string, createdAt: string, currency: string, id: string, name: string, tenantId: string, updatedAt: string, config?: { [string]: unknown } } Source: packages/types/src/wallets.ts

backendType: Settlement backend the wallet is denominated in: crypto (on-chain assets), fiat (national currency), or credits (internal accounting units). Determines how balances and transactions are settled. balance: Current balance as a decimal string in the wallet's currency. Stored as a string to preserve precision for both crypto and fiat amounts. config: Backend-specific configuration for the wallet (for example chain or account details for a crypto backend). Shape depends on backendType; not interpreted by the hub.