Connecting an agent
Connecting an agent establishes four linked pieces:
Recipe (git-backed behavior)
→ Runtime version (deployable execution)
→ Staging lane + bindings (where and with what it runs)
→ Task → Conversation (work and its captured record)- A recipe is the agent behavior—agents, instructions, skills, and judges—pinned to an exact Git commit.
- A runtime version combines that immutable recipe with the execution policy and resources needed to run it. Related versions share one stable runtime group.
- An environment lane selects which version and bindings serve development, staging, or production traffic.
- A task is one durable execution. Its conversation is the evidence used by observations, judges, and experiments later in the loop.
Before you start
You need a project whose GitHub integration already has access to the repository. Runtime bootstrap also requires a clean checkout of pushed main: HEAD must equal origin/main, and origin must be that GitHub repository.
npm install -g @introspection-ai/cli
npm install @introspection-sdk/introspection-node
introspection login
introspection whoami
git status --short
git branch --show-current
git rev-parse HEAD origin/mainStop if the two SHAs differ or the status is not empty. whoami must identify the intended project and include the runtime/task scopes used below.
Runtime bootstrap, staging selection, and bindings are operator mutations and remain CLI-only. Task execution is available through both surfaces, so that step uses SDK/CLI tabs.
1. Validate and bootstrap
The manifest is the repository-level declaration that connects the recipe package to its runtime defaults. Its filename is the stable runtime-group slug, so later commits become new versions of the same logical agent instead of unrelated runtimes. This example assumes .introspection/support-agent.yaml points at the recipe package in the same repository.
introspection recipes validate --profile publish
introspection runtimes create \
--manifest .introspection/support-agent.yaml > runtime.json
export RUNTIME_ID=$(jq -r '.id' runtime.json)
export RUNTIME_GROUP_ID=$(jq -r '.runtime_group_id' runtime.json)
export RECIPE_ID=$(jq -r '.recipe_id' runtime.json)
test "$RUNTIME_ID" != null
test "$RUNTIME_GROUP_ID" != null
test "$RECIPE_ID" != nullSuccess means validation exits 0 and all three IDs are present. Image creation is asynchronous; wait at most five minutes for readiness:
for attempt in {1..60}; do
introspection runtimes get "$RUNTIME_ID" > runtime-current.json
IMAGE_STATUS=$(jq -r '.image_status' runtime-current.json)
[ "$IMAGE_STATUS" = ready ] && break
[ "$IMAGE_STATUS" = failed ] && { jq . runtime-current.json; exit 1; }
sleep 5
done
test "$IMAGE_STATUS" = ready2. Point staging at the version
Staging is the fast iteration lane. Tracking main advances it as the repository integration creates new versions; pinning freezes it on one exact version for a controlled test.
introspection runtimes staging track "$RUNTIME_ID" --git-ref main
introspection runtimes versions "$RUNTIME_ID" -o tableUse staging pin instead when staging must remain on this exact version while new commits arrive.
3. Satisfy declared bindings
Bindings provide environment-specific configuration without placing secrets in the recipe. A recipe declares what it needs; the operator connects concrete endpoints, readable variables, and write-only credentials at the project, runtime-group, runtime, or environment scope.
Skip this step when the recipe uses the managed model and declares no external bindings. For a declared MCP server named linear, keep the secret out of argv:
export LINEAR_TOKEN='replace-me'
introspection bindings credentials create \
--name LINEAR_TOKEN \
--value-env LINEAR_TOKEN \
--runtime-group "$RUNTIME_GROUP_ID" \
--environment staging
introspection bindings mcp connect \
--recipe "$RECIPE_ID" \
--mcp-server-id linear \
--name Linear \
--endpoint-url https://mcp.example.com/mcp \
--header 'Authorization=Bearer ${LINEAR_TOKEN}' \
--runtime-group "$RUNTIME_GROUP_ID" \
--environment staging
introspection bindings mcp list \
--recipe "$RECIPE_ID" \
--runtime-group "$RUNTIME_GROUP_ID" \
--environment stagingSuccess means every required declaration is connected and no row reports a missing required binding. See introspection bindings mcp connect --help when the endpoint needs credential-backed headers.
4. Create and follow the first task
Running the runtime opens a sandbox under an end-user identity. Starting a task creates the first run; later prompts or interrupt responses create additional runs on the same durable task.
JavaScript SDK
import { IntrospectionClient } from "@introspection-sdk/introspection-node";
const client = new IntrospectionClient({
token: process.env.INTROSPECTION_TOKEN,
});
const runner = await client.runtimes("support-agent").run({
identity: { user_id: "docs-smoke-1" },
});
const handle = await runner.tasks.start({
prompt: "Reply with the word ready.",
});
for await (const event of handle.stream()) {
console.log(event.event, event.data);
}
await runner.close();Use a staging-scoped INTROSPECTION_TOKEN. For only the final text, replace the stream loop with const reply = await handle.text().
In the CLI tab, follow emits one AG-UI event per JSONL line and returns when the run settles. Preserve the highest numeric sequence if you reconnect; pass it back with --since. A resume_gap event means the bounded replay window no longer contains every missing event, so refetch the task and conversation instead of assuming a complete stream.
If the run pauses for input, inspect metadata.pending_interrupts in task-final.json, answer the complete batch, then follow the new current run:
introspection tasks resume "$TASK_ID" \
--interrupt-id <id-from-metadata> \
--payload '{"answer":"approved"}'
introspection tasks follow "$TASK_ID" --run current --since 0
introspection tasks get "$TASK_ID" > task-final.json
jq -e '.status == "idle" or .status == "completed"' task-final.jsonresume rejects partial batches. Provide each pending interrupt exactly once,
using --cancel-interrupt for any answer you intentionally cancel.
Done when
runtimes getreturns the expected immutable version and runtime group.- Required staging bindings are connected.
tasks followsettles without an unhandled interrupt.tasks getends atidleorcompleted;failed,cancelled, andawaiting_userare not success.
Keep RUNTIME_ID, RUNTIME_GROUP_ID, and TASK_ID; the next guide uses them.
Next
- Observing & investigating: find the recorded conversation and work from a pattern down to its transcript.