Skip to main content
Most embedded agents do not live in a chat box you built. They live on a surface your users already use: an external provider your own integration bridges, or a support queue inside your product. Installing an agent is how you put a published Agent on those surfaces so Automations and agent-to-agent flows can execute there. Three resources compose the placement. They reference each other; none copies the others’ data.

ExternalInstallation

A verified, Workspace-owned installation of one provider, such as one Slack app installation. exti_…

SurfaceScope

A governed place inside that installation: the provider root, a team, a channel, or a DM. surf_…

AgentInstallation

The binding that places one Agent on specific surface scopes under a declared identity posture. aini_…

The provider installation

An ExternalInstallation is an authenticated link to one provider tenant your integration operates. A given (provider, external tenant) has at most one active Checkfu Workspace owner. Creating or reactivating one requires a signed pairing proof bound to the exact Workspace, provider tenant, operation, and installation, and valid for at most five minutes. Your provider adapter produces that proof; Checkfu verifies it.
The response reports state (active, disabled, disconnected, or uninstalled). Provider credential material never appears on the resource, in a Session, or in a harness.

The surface hierarchy

A SurfaceScope is a governed place in an installation, and it is the provider-neutral handle everything else uses. PermissionAssignments, ActionPolicies, Memory, Budgets, Automations, audit, and retention all address a SurfaceScope. Provider-specific channel or DM identifiers never enter Session state. Each scope has a kind and, unless it is the root, a parent_id: A scope also declares visibility (public, private, personal), membership (public, provider_members, personal), and inheritance (inherit or isolate). The tree must be acyclic, (installation, external_id) is unique, and there is no DELETE. A scope’s lifecycle ends by patching its state to archived.
A thread inside a channel is not another SurfaceScope. A thread maps to a Session through a conversation binding; the SurfaceScope is the channel it lives in.

Placing the agent

An AgentInstallation is the binding that makes an Agent answerable on surfaces. It coordinates references: it never copies the definition, and it never introduces a second access-control list.
What the placement binds: There are no harness or model “override” objects here. The logical names name the same contract the Agent’s published release already resolves to; the installation coordinates, it does not reconfigure. The identity posture declares whose authority the placement runs under, and admission rejects a mismatch rather than guessing:
  • autonomous (the default when identity_posture is omitted): the placement acts as its own credential-bearing service Principal, which owns its Connections and PermissionAssignments. acted_as must be a service-kind Principal in the Workspace.
  • delegated: the placement acts on behalf of a resolved user. acted_as must be a person-kind Principal, so per-user PermissionAssignment intersection evaluates a real human.
A delegated request differs only in those two fields:
The lifecycle is active ↔ disabled → archived; archived is terminal. Changing acted_as or identity_posture revalidates authority and fences both the old and new Principal.

Installed session admission derives everything

When a Session starts from an installation, the caller supplies almost nothing. The platform derives the rest from the placement, and supplying a derived field is rejected, not ignored. An installed session request may set only:
  • agent_installation: the placement
  • surface_scope: which scope, within that placement, the Session runs in
  • principal: the human on whose behalf it is being started
  • mounts: Project mounts only
  • title: an optional human label for the Session
  • initial_events: up to 50 optional events, applied in order, to seed the log with at creation
It may not set agent_deployment_id, agent_deployment_revision_number, version_policy, acted_as, caused_by, harness, model_routing_profile_key, environment, or compaction. Each of those is derived from the installation. Sending any of them fails validation with 400 validation.malformed. The request is refused, so a caller can never quietly override the Harness, model, or acting identity a placement was governed to use. Admission then checks the full chain: an active placement in an active ExternalInstallation; the selected SurfaceScope and its complete ancestor chain all active; the requester is an active person holding invoke on both the Agent and the SurfaceScope; the placement’s acting Principal is active, matches the declared identity posture, and holds act_as; and the deployment still pins its own use_harness, use_model, and use_environment authority. The resulting Session freezes the placement, surface, requester, actor, the exact deployment revision, and the release hash it pins. See Two freeze horizons.
Per-Session compaction overrides are rejected in v1; the frozen Agent supplies the effective policy. Check capability status for the live posture of the collaboration surface.

Where a Session comes from

You rarely create an installed Session directly. On a live surface, the first message in a thread creates it through a conversation binding, which runs exactly this installed admission for you. Direct POST /v1/sessions with an installed request is the path only when you are not routing through a provider conversation.

Next steps

Conversation bindings

Turn an inbound thread into a Session, race-safely.

Add an agent to your app

The full placement-to-billing journey, end to end.