Skip to content
Agent Orchestration
Skill

/agent-canvas-environment

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.

BOOST
From plugin
extensions
17185 skills4 commands
Install
$ npx -y skills add openhands/extensions --skill agent-canvas-environment --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/agent-canvas-environment

Context preview

The summary Claude sees to decide when to auto-load this skill.

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.

SKILL.md

agent-canvas-environment.SKILL.md
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:

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:

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:

  • the **encrypted** `agent_settings` from `GET /api/settings` (with `X-Expose-Secrets: encrypted`), which carries the real Fernet-encrypted `llm.api_key`, the existing `agent_context`, and the agent kind — so you never handle plaintext credentials and you don't drop the caller's skill/context config
  • `secrets_encrypted: true` so the agent-server decrypts that `api_key` server-side
  • the exec tool set merged into `agent_settings.tools` (and `task_tool_set` when you enable sub-agents)
  • `tool_module_qualnames` for any non-SDK tools (e.g. `canvas_ui`)
  • `agent_context.load_public_skills`/`load_user_skills`/`load_project_skills` set to `true` if the delegated agent should inherit bundled/user/project skills
  • a fresh absolute workspace directory
  • `initial_message.run: true`
  • `worktree: false` when the workspace is already isolated

Credential handling — important

`GET /api/settings` (default) **masks** every credential — `llm.api_key` comes back as the literal string `"**********"`. If you forward that verbatim, the new conversation authenticates with the placeholder and fails immediately with `LLMAuthenticationError` (`You must provide an API key`).

The supported way to obtain forwardable credentials is the **`X-Expose-Secrets: encrypted`** request header. With it, `/api/settings` returns the real `llm.api_key` as a **Fernet-encrypted token** (starts with `gAAAAA`) intended to be sent back to the server with `secrets_encrypted: true`; the agent-server's `decrypt_incoming_llm_secrets` decrypts it server-side. Do **not** read `~/.openhands/profiles/*.json` directly — that is brittle (the caller may not share the backend's home directory, `active_profile` may be null, the profile store may live elsewhere).

Two working approaches:

1. **`agent_profile_id` (simplest, but no tools)** — send only `agent_profile_id: "<uuid>"` (from `GET /api/agent-profiles` → the profile whose `id` equals `active_agent_profile_id` from `/api/settings`). The server resolves the LLM key + agent kind from the profile. Mutually exclusive with `agent`/`agent_settings`, and the `openhands` agent-profile schema forbids `tools`/`include_default_tools`, so the conversation gets **zero exec tools** this way. Use only when the task needs no tools.

2. **Encrypted `agent_settings` (full tools, preserves context)** — start from the encrypted `/api/settings` `agent_settings` payload, drop `schema_version` and `mcp_config` (to avoid MCP-connection failures at creation time), merge in the exec tool set and `load_*_skills` flags, and send with `secrets_encrypted: true`. This is the pattern for real delegated work.

Template (full tools, preserves context):

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"

# Fetch the agent_settings with ENCRYPTED secrets exposed. This returns the
# real llm.api_key as a Fernet token (gAAAAA...) plus the existing
# agent_context/agent kind, so we preserve the caller's config and never
# handle plaintext credentials.
SETTINGS_JSON="$(curl -sS -H "X-Session-API-Key: $KEY" -H "X-Expose-Secrets: encrypted" "$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" '
  # Start from the encrypted agent_settings so llm.api_key (Fernet token),
  # agent_kind, and agent_context are preserved. Drop schema_version and
  # mcp_config (MCP servers can fail to connect at creation time; the profile
  # can be re-resolved later if needed).
  def base_ag
Read more
Ships withextensions

This repository is the public extensions registry for OpenHands. It contains reusable, shareable skills, plugins, and Agent Canvas Apps that customize agent behavior and interfaces. Skills overview docs: SDK skill guide:

Get the whole plugin

Other skills on extensions.