diff --git a/control-plane/internal/skillkit/skill_data/agentfield-use/SKILL.md b/control-plane/internal/skillkit/skill_data/agentfield-use/SKILL.md index 1e54edae2..122ab272b 100644 --- a/control-plane/internal/skillkit/skill_data/agentfield-use/SKILL.md +++ b/control-plane/internal/skillkit/skill_data/agentfield-use/SKILL.md @@ -210,6 +210,60 @@ Long-running agents can take tens of minutes — poll with backoff (start ~5s, settle at ~30s) and tell the user what is in flight. For live progress, stream Server-Sent Events from `GET /api/v1/executions//events`. +### If the result carries a `workspace_handle`, you can read the files + +Some agents (SWE-AF) mirror the workspace they are building in, so you can open +the actual files instead of reasoning from the summary — including uncommitted +edits and untracked files that no git push would carry. You do not ask whether +this is available and there is nothing to configure: the handle is in the result +when it works and absent when it doesn't. + +```json +"workspace_handle": {"v":1, "remote":"ssh://host:port"|"dir:/path", + "namespace":"...", "key":"<64 hex>", "token":"..."} +``` + +`furrow` is rarely on PATH. AgentField installs it to `~/.agentfield/bin/`, and a +node that ships its own copy keeps it inside the installed package. Resolve it +from those; do not try to install it yourself. + +```bash +os=$(uname -s | tr A-Z a-z) +furrow_bin() { # $1 = furrow | furrow-dial + command -v "$1" 2>/dev/null && return + for c in ~/.agentfield/bin/"$1" ~/.agentfield/packages/*/{bin,go/bin}/"$1"-"$os"-*; do + [ -x "$c" ] && { echo "$c"; return; } + done +} +FURROW=$(furrow_bin furrow) DIAL=$(furrow_bin furrow-dial) +``` + +A `dir:` handle needs only `$FURROW`; an `ssh://` handle needs `$DIAL` too. If +either is missing, say so plainly and carry on from the result — the mirror is +fine, this machine just has no client for it. + +```bash +# ssh:// handle — furrow-dial carries the protocol; nothing else changes +export FURROW_SSH_COMMAND="$DIAL" FURROW_DIAL_TOKEN= FURROW_DIAL_INSECURE=1 +FURROW_RECOVERY_KEY= "$FURROW" clone / ./run-workspace --no-watch + +# dir: handle (same machine) — clone rejects directory remotes, so pair instead. +# The path is the handle's remote with the "dir:" prefix removed; don't append +# anything to it. +git init -q run-workspace && "$FURROW" --repo run-workspace watch --no-daemon +"$FURROW" --repo run-workspace pair --name --key +"$FURROW" --repo run-workspace sync --pull --bootstrap +``` + +`"$FURROW" --repo run-workspace sync --follow` keeps it current while the run +works. Read and diff freely. Treat it as a mirror, not a shared drive: it is +one-writer, and edits go back as a merge (`furrow merge --check ""`), +so change files between issues or on a fork rather than while the agent writes. + +`get_workspace_handle` re-fetches a handle mid-run: +`POST /api/v1/execute/.get_workspace_handle` with `{"input":{"run_id":"..."}}`. +`{"available": false}` means no mirror — carry on without it. + **Several at once:** `POST /api/v1/executions/batch-status` with `{"execution_ids": [...]}`. Terminal entries embed the FULL result payload — responses can be large (100KB+), so write to a file and parse from there; never @@ -280,6 +334,9 @@ is enabled), and verify offline with `af verify audit.json`. ## Hard rules - Every call goes through the control plane — never POST to an agent's own port. + The one exception is a `workspace_handle`: its `ssh://` endpoint is a furrow + transport, not the agent's HTTP port, and the per-run token in the handle is + what authorizes it. Reading files there is not an agent call. - Kwargs live under `"input"`. Empty input is `{"input": {}}`. - Async + poll for anything that might exceed a few seconds; sync is for quick lookups only. Independent async calls go out together, not one at a time. diff --git a/skills/agentfield-use/SKILL.md b/skills/agentfield-use/SKILL.md index 05f49f1fd..122ab272b 100644 --- a/skills/agentfield-use/SKILL.md +++ b/skills/agentfield-use/SKILL.md @@ -223,23 +223,39 @@ when it works and absent when it doesn't. "namespace":"...", "key":"<64 hex>", "token":"..."} ``` -Use it only if `furrow` is on PATH (and, for an `ssh://` handle, `furrow-dial`). -Otherwise ignore it silently and work from the result as usual. +`furrow` is rarely on PATH. AgentField installs it to `~/.agentfield/bin/`, and a +node that ships its own copy keeps it inside the installed package. Resolve it +from those; do not try to install it yourself. + +```bash +os=$(uname -s | tr A-Z a-z) +furrow_bin() { # $1 = furrow | furrow-dial + command -v "$1" 2>/dev/null && return + for c in ~/.agentfield/bin/"$1" ~/.agentfield/packages/*/{bin,go/bin}/"$1"-"$os"-*; do + [ -x "$c" ] && { echo "$c"; return; } + done +} +FURROW=$(furrow_bin furrow) DIAL=$(furrow_bin furrow-dial) +``` + +A `dir:` handle needs only `$FURROW`; an `ssh://` handle needs `$DIAL` too. If +either is missing, say so plainly and carry on from the result — the mirror is +fine, this machine just has no client for it. ```bash # ssh:// handle — furrow-dial carries the protocol; nothing else changes -export FURROW_SSH_COMMAND=furrow-dial FURROW_DIAL_TOKEN= FURROW_DIAL_INSECURE=1 -FURROW_RECOVERY_KEY= furrow clone / ./run-workspace --no-watch +export FURROW_SSH_COMMAND="$DIAL" FURROW_DIAL_TOKEN= FURROW_DIAL_INSECURE=1 +FURROW_RECOVERY_KEY= "$FURROW" clone / ./run-workspace --no-watch # dir: handle (same machine) — clone rejects directory remotes, so pair instead. # The path is the handle's remote with the "dir:" prefix removed; don't append # anything to it. -git init -q run-workspace && furrow --repo run-workspace watch --no-daemon -furrow --repo run-workspace pair --name --key -furrow --repo run-workspace sync --pull --bootstrap +git init -q run-workspace && "$FURROW" --repo run-workspace watch --no-daemon +"$FURROW" --repo run-workspace pair --name --key +"$FURROW" --repo run-workspace sync --pull --bootstrap ``` -`furrow --repo run-workspace sync --follow` keeps it current while the run +`"$FURROW" --repo run-workspace sync --follow` keeps it current while the run works. Read and diff freely. Treat it as a mirror, not a shared drive: it is one-writer, and edits go back as a merge (`furrow merge --check ""`), so change files between issues or on a fork rather than while the agent writes.