agent-canvas-environment · git:20260619.bb34a76 · 2026-06-19 · sha256 a6fc872e8a86b5c6

agent-canvas-environment git:20260619.bb34a76A

Immutable. This exact content is served forever at /api/v1/blob/a6fc872e8a86b5c6.

---
name: agent-canvas-environment
description: Work effectively inside a local Agent Canvas environment, including local agent-server auth, frontend/backend port discovery, safe workspace hygiene, and delegating work to a new local conversation through POST /api/conversations.
triggers:
- agent canvas
- agent-canvas
- local conversation
- delegate local conversation
- session api key
- X-Session-API-Key
- localhost:8001
---

# Agent Canvas Environment

Use this skill when running inside or alongside a local Agent Canvas stack, especially when the user asks to inspect the local backend, create or monitor local conversations, or delegate work to another local conversation.

## Core rules

- Treat the local Agent Canvas backend as an agent-server API, usually `http://localhost:8001`.
- Treat the local UI as a separate frontend, usually `http://localhost:8000`.
- Do not print session API keys. Pass them directly in `X-Session-API-Key`.
- Trust any runtime-services block or explicit user-provided host over default ports.
- Before mutating a repository, check `git status -sb`. If a worktree has unrelated changes, use a separate worktree or clone.
- When delegating, write a self-contained prompt. The new conversation does not inherit the current chat context.

## Find the session key

Use the first available value, without echoing it:

```bash
KEY="${SESSION_API_KEY:-${OH_SESSION_API_KEYS_0:-${LOCAL_BACKEND_API_KEY:-}}}"
if [ -z "$KEY" ] && [ -f "$HOME/.openhands/agent-canvas/api-key.txt" ]; then
  KEY="$(tr -d '\n' < "$HOME/.openhands/agent-canvas/api-key.txt")"
fi
test -n "$KEY" || { echo "No Agent Canvas session API key found" >&2; exit 1; }
```

Validate backend access:

```bash
curl -sS -o /tmp/agent-canvas-conversations.json -w '%{http_code}\n' \
  -H "X-Session-API-Key: $KEY" \
  http://localhost:8001/api/conversations/search
```

HTTP `200` means the backend and key work.

## Delegate to a local conversation

Use `POST /api/conversations` with:

- current `/api/settings` as the base agent profile
- a fresh absolute workspace directory
- `initial_message.run: true`
- `worktree: false` when the workspace is already isolated

Template:

```bash
set -euo pipefail

BASE="${AGENT_CANVAS_BACKEND:-http://localhost:8001}"
KEY="${SESSION_API_KEY:-${OH_SESSION_API_KEYS_0:-${LOCAL_BACKEND_API_KEY:-}}}"
if [ -z "$KEY" ] && [ -f "$HOME/.openhands/agent-canvas/api-key.txt" ]; then
  KEY="$(tr -d '\n' < "$HOME/.openhands/agent-canvas/api-key.txt")"
fi
test -n "$KEY" || { echo "No Agent Canvas session API key found" >&2; exit 1; }

WORKDIR="${WORKDIR:-$HOME/workspace/delegated/$(date +%Y%m%d-%H%M%S)}"
mkdir -p "$WORKDIR"

SETTINGS_JSON="$(curl -sS -H "X-Session-API-Key: $KEY" "$BASE/api/settings")"
PROMPT='Write a complete, task-specific prompt here. Include repo, branch, constraints, validation, and expected report.'

PAYLOAD="$(jq -n --argjson settings "$SETTINGS_JSON" --arg prompt "$PROMPT" --arg workdir "$WORKDIR" '
  def agent_settings:
    ($settings.agent_settings // {})
    | del(.schema_version)
    | . + {
        agent_context: ((.agent_context // {}) + {
          load_public_skills: true,
          load_user_skills: true,
          load_project_skills: true
        })
      };
  ($settings.conversation_settings // {}) as $conv |
  {
    agent_settings: agent_settings,
    workspace: {kind: "LocalWorkspace", working_dir: $workdir},
    confirmation_policy: {kind: "NeverConfirm"},
    max_iterations: (($conv.max_iterations // 80) | if . == null then 80 else . end),
    stuck_detection: true,
    autotitle: true,
    worktree: false,
    initial_message: {
      role: "user",
      content: [{type: "text", text: $prompt}],
      run: true
    }
  }
')"

curl -sS -X POST "$BASE/api/conversations" \
  -H "Content-Type: application/json" \
  -H "X-Session-API-Key: $KEY" \
  --data-binary "$PAYLOAD" | jq '{id, title, execution_status, workspace}'
```

Report both links:

- UI: `http://localhost:8000/conversations/<conversation_id>`
- API: `http://localhost:8001/api/conversations/<conversation_id>`

## Monitor a delegated conversation

```bash
CID="<conversation_id>"
curl -sS -H "X-Session-API-Key: $KEY" "$BASE/api/conversations/$CID" \
  | jq '{id, title, execution_status, updated_at, workspace, agent_kind: .agent.kind, current_model_id, current_model_name}'

curl -sS -H "X-Session-API-Key: $KEY" "$BASE/api/conversations/$CID/events/search?limit=20" \
  | jq '.events // .items // .'
```

Terminal statuses commonly include `idle`, `running`, `finished`, `error`, `stuck`, and `stopped`.

## Prompt checklist for delegation

Include:

- repository owner/name and local path if relevant
- branch, PR, issue, or Linear ticket identifiers
- current status and known blockers
- exact files or subsystems in scope
- dirty-worktree warnings and paths not to touch
- whether to push, open a PR, or only report
- checks/tests to run
- expected final report format

Do not rely on the new conversation knowing anything from the current thread.