Skip to main content
This guide accompanies software-agent-sdk #5010. Use a build containing that change and the server’s conversation-scoped runtime APIs. Publish this guide with the corresponding SDK release.
Use RemoteConversation.create to create an agent conversation from a saved profile and RemoteConversation.attach to connect to an existing conversation. Use RemoteWorkspace for its files, commands, and runtime lifecycle. AsyncRemoteWorkspace provides the same workspace operations for async callers. The SDK owns HTTP routes, authentication headers, and conversation scope. The caller owns scheduling, admission limits, workflow selection, and completion policy. Canvas uses the TypeScript client for the same API boundary.

Create a Conversation From a Saved Profile

A dispatcher selects a unique conversation ID and workspace directory. Use /workspace for a Docker conversation, or an absolute local run directory for a local server. workspace.get_server_info()["conversation_runtime"] reports the server’s configured runtime mode. This selection belongs to the dispatcher; the automation bundle receives the same environment in either mode.
create sends a typed creation request directly to the server. The server resolves the saved profile. The dispatcher does not load its model, tools, or secret values. runtime_conversation_id binds the workspace’s existing file, command, and Git operations to that conversation and cannot be changed on the workspace instance. Omitting it selects the legacy host workspace; runtime credential handoff and release require an explicit conversation scope.

Start and Observe a Bundle

After uploading and extracting its bundle, a dispatcher starts the configured entrypoint with workspace.start_command(command, timeout=...). This returns a command ID without waiting. workspace.get_command_output(command_id) returns the latest matching output record; None or a missing exit code means the command has not completed. Always inspect the actual command’s exit code before accepting completion. workspace.execute_command(...) remains the foreground operation and returns a CommandResult. Async callers use the same scope and operations:

The Bundle Interface

Supply AGENT_SERVER_URL, SESSION_API_KEY, AUTOMATION_CONVERSATION_ID, and WORKSPACE_BASE to each bundle. The same code works in either workspace:
attach fetches an existing conversation and connects to its server-resolved agent, including ACP agents. A missing or inaccessible conversation fails; attachment never creates a conversation or reloads its profile. Run completion, callbacks, structured events, and errors follow the existing conversation lifecycle. Read conversation.state.events for the event history. delete_on_close defaults to False, so closing this handle preserves the server conversation and the caller-owned workspace. Register the remote agent’s tool schemas before connecting: register_default_tools() covers standard tools, including browser events; register additional custom tools separately.

Select Secrets With an Agent Profile

Profile secret selection requires the profile secret_refs and Docker integration changes tracked in SDK #5014. Keep this section unpublished until that integration is released. Servers with profile-secret enforcement advertise profile_secret_scope_v1 in /server_info.capabilities; clients should use that capability instead of a guessed release version when offering a scope picker. Set secret_refs on the saved agent profile to an explicit list of secret names, for example ["GITHUB_REVIEWER_TOKEN"]. The profile stores names only. A launch using that profile receives the selected saved secrets without the dispatcher copying every secret into the request. An empty list permits no user secrets; null preserves the existing request-only, unrestricted behavior. The Agent Server applies the same selection before local conversation construction and before Docker secret materialization. Extra request secrets are discarded before their lookup runs. For a selected name present in the server’s secret store, the stored value takes precedence over a caller-supplied value or lookup. Names missing from the store can still match explicitly supplied conversation secrets. The agent’s secret registry advertises selected names and descriptions in the system prompt and exports selected values to tools when needed. Values are never included in the prompt. Docker handoff encrypts them with the runtime’s key. LLM profile credentials and selected MCP credentials have their own delivery channels. Restrict mcp_server_refs, tools, and other profile capabilities as well. A secret allow-list does not narrow the external provider’s token permissions: issue repository-scoped credentials appropriate to each automation’s role.

Credentials and Lifecycle Ownership

Only a trusted orchestrator should call workspace.get_runtime_session_key(). On a Docker server supporting credential handoff, it returns the selected inner runtime’s key. The dispatcher supplies that key and the runtime-reachable server URL to the worker. Keep the outer control-plane key outside the worker. Local workspaces retain the local server’s credential boundary and are not security sandboxes. Use Docker isolation and role-scoped external-service grants when running untrusted repository code. After a Docker run has stopped and its result is recorded, the dispatcher calls workspace.release_runtime(). This releases that runtime while preserving conversation history. A missing runtime is treated as already released; other failures are reported. A persistent local server should be retained by its owner. Workspace context managers close their own HTTP connections. Closing a conversation handle does not release its runtime or delete history unless delete_on_close=True was explicitly selected. These SDK operations do not choose a workflow, post an acceptance decision, or schedule another run.