Divide responsibility once
Never send a Workspace API key to the browser. Resolve the signed-in user and the builder document on your backend, then call Checkfu from that trusted server boundary.
Use the generated SDK surface
The SDK request types come from the generated operation catalog. Accept those types at your boundary instead of maintaining a second hand-written Agent schema:checkfu.agents and checkfu.sessions. Do not wrap them in a parallel compatibility client.
Your backend should associate one idempotencyKey with each logical create or save and retain the exact submitted body. If a response is lost, retry with that same key and body within the API’s replay window. A later edit is a new save with a new key. Reusing a key with changed content conflicts; do not replace the key automatically to bypass that refusal.
The SDK keeps a mutation key stable across its own transport retries. Without an explicit key, a separate call creates a new one, so the SDK cannot connect that call to the earlier save. These helpers require the key and forward the SDK’s other request options, including signal. Aborting a request does not undo a save the server already accepted; recover its result with the original key and body. Recheck the signed-in user’s access to the builder document before every call, including a retry.
A material update advances the mutable Agent and creates the next immutable AgentVersion. Preserve the current version field when the generated update body uses it as the optimistic-concurrency guard. A stale browser tab should receive a conflict, reload the current Agent, and ask the person to merge intent. It should not overwrite a newer version silently.
Create the Environment separately
Environment is a canonical Workspace resource, not an inline execution recipe hidden in the builder document. Create or select it through its own operation and store its ID beside your host object:Start a preview Session
Grant the Agent use of the Environment once when the user connects them. Then start a preview Session and send the preview prompt. The grant and the Session use the same public operations as the quickstart:agent: { type: "agent", id: agentId, version: savedAgent.version } alongside
environment_id. Include acted_as when the selected Agent uses governed
Connections. Keep that Principal selection under your backend’s authorization.
This helper sends the prompt as a separate event, so its input excludes
initial_events; use the Session create operation directly for that mode.
Session admission resolves and freezes the AgentVersion and Environment. The
message starts the preview turn; pass the observed events to the signed-in
user through your backend. The stream follows events after that input. An
idle boundary with stop_reason: "requires_action" needs a tool result or
approval before the turn settles. Editing the Agent later does not mutate that
Session. Start another Session to preview the next AgentVersion.
The create body accepts an optional acted_as naming a live Principal that holds act_as on the selected Agent. Admission checks that authority and freezes the Principal, and a Session whose Agent uses governed Connections requires it. The body never creates a Principal and does not accept author attribution. Do not restore retired attribution fields in a compatibility wrapper.
Preview from the CLI
With the private-alpha CLI artifact, save the same Session create body insession.json, including the exact saved agent.version
and any required acted_as. Then start and follow the preview:
initial_events.
Use session create --input @session.json --idempotency-key <caller-key> when
creation must be recoverable across invocations, then chat with the returned
Session ID using --session. Keep the original body and key when retrying
creation; a changed saved version or Principal is a new intent. API admission
checks the selected Principal’s authority for either path.
Keep configuration changes coordinated
Choose the configuration source the builder edits and apply through its supported operations. A Save button does not create an ownership reservation.Direct Agent configuration
The backend may call the canonical Agent operation directly. The UI and SDK remain interfaces, not owners.Checked-in Agent project
If the builder edits a checked-in Agent project, apply it withcheckfu agent apply or the equivalent Agent create and update calls. Pass the
Agent ID so the directory stays bound to one Agent. Other resources, such as
Budgets, grants, Connections, Automations, and Memory, are created through their
own operations. No command applies them from a file.
AutomationGraph configuration
Use the registered AutomationGraph revision and plan/apply lifecycle for graph configuration. The resulting Automation still owns firing and the resulting Session still owns execution.Resource conflicts
Inspect the exact typed error before retrying. A name match is not permission to adopt or overwrite a resource, and a different interface does not bypass the underlying operation’s checks. See Authoring authority.Embed source-controlled authoring
A builder can also edit YAML or Git-backed source. In that mode:- save the proposed source change to the user’s repository or review branch;
- compile and plan it with the version-matched source compiler;
- show the plan without treating it as a claim;
- apply the reviewed Agent changes through canonical Agent operations; and
- surface authorization, concurrency, or resource-policy errors to the user.
Custom tools
checkfu.tools.sync(agentId, tools) invokes canonical Agent updates and the governed ActionPolicies required by needsActionApproval. Keep the declarations coordinated with the configuration source your builder edits, and handle the ordinary operation errors. It does not create a source-ownership or handoff lifecycle.
The serving loop stays in your application:
Verification checklist
Verify that the embedded journey proves all of these boundaries:- the API key never reaches the browser;
- the backend rechecks host-object ownership for reads and writes;
- the same-key, same-body save recovers its result after a lost response, while changed-body reuse conflicts;
- stale Agent updates conflict rather than overwrite;
- an active source-owner conflict is shown and not retried through another interface;
- an existing Session keeps its frozen AgentVersion after an edit;
- a new Session admits the updated AgentVersion and selected Environment; and
- consequential Custom tools wait for the governed ActionApproval before the app-owned handler runs.