Skip to content
Merged
140 changes: 140 additions & 0 deletions docs/agent37.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# Agent37 adapter
Comment thread
kjgbot marked this conversation as resolved.

Everything below was measured on a live Agent37 instance on 2026-08-25, on the
provider's default system template. Where a fact is shared with another
provider it says so, because two of the things previously logged as "Agent37
defects" are not properties of Agent37 at all.

## The template, and the one setting that matters

```text
user node (uid 1000, gid 1000)
HOME /home/node
cwd / (the exec plane's default when no cwd is given)
os Debian GNU/Linux 12 (bookworm)
kernel 4.19.0-gvisor
shape 2 vCPU · 4096 MB · 10 GB
shell sh (dash) — NOT bash
```

**Construct `Agent37Runtime` with `defaultHomeDir: "/home/node"`.** This is the
single most consequential line in an Agent37 integration.

`/root` **exists** — as `drwx------ root root` — and the template user cannot
enter it. So a launch that sets `workdir: '/root'` does not fail once, it fails
*every command on the box*, identically:

```console
$ id; echo PWD=$PWD → exit 1
sh: 1: cd: can't cd to /root
```

Ten unrelated probes were run that way and all ten returned exit 1. Re-pointed
at `/home/node`, all ten passed. Note the correction to an earlier note: `/root`
is **unreachable, not missing**, and the distinction matters because "missing"
sends you looking at the image while "unreachable" sends you to the one line of
caller configuration that actually causes it.

Since a bare `cd … || exit 1` is indistinguishable from the command's own exit
1, the adapter no longer emits one. A failed `cd` now raises
`Agent37WorkdirUnusableError`, which names the directory and the instance. See
`AGENT37_WORKDIR_UNUSABLE_EXIT_CODE`.

## The exec plane is dash

`agent37`'s exec runs POSIX `sh`, not bash. A bashism does not error usefully —
`${PIPESTATUS[0]}` comes back as `Bad substitution`, so a step that looks like
it succeeded quietly did nothing. Anything this package generates for an
Agent37 box is POSIX; anything a caller generates should be too.

## There is no root, and that is not an Agent37 property

`sudo` is inert (`effective uid is not 0 … nosuid`) and `mkdir /opt/<anything>`
returns `Permission denied`.

**The same `mkdir /opt` is denied on Daytona**, measured in the same run, so it
should stop being recorded as an Agent37 defect. Nothing needs root: npm's
global prefix is already `/home/node/.npm-global` and already on PATH, and
`/home/node`, `/home/node/.local/bin` and `/tmp` are all writable.

## What the image does not ship

| | Agent37 | Daytona |
| --- | --- | --- |
| `node` / `npm` | v24.19.0 / 11.17.0 | present |
| `git`, `curl`, `ssh`, `python3` | present | present |
| `gh` | **absent** — `gh --version` → **exit 127** | **absent** — **exit 127** |
| `relayfile-mount` | **absent from PATH** | `/usr/local/bin/relayfile-mount` |
| `agent-relay` | absent (installs from npm in ~46 s) | present in the image |

Egress is open: `registry.npmjs.org` and the Agent Relay control plane both
answered `200`.

Both gaps close in userspace with no root — see `src/bootstrap.ts`:

- `buildRelayfileMountLinkShell` symlinks the daemon that `agent-relay` already
vendors as `@relayfile/mount-<platform>-<arch>`. No download.
- `buildGhInstallShell` drops a release tarball into `~/.local/bin`; measured at
about three seconds, moving `gh --version` from exit 127 to exit 0.

`gh auth status` then returns **exit 1** ("not logged into any GitHub hosts").
Keep the two apart when reporting: a present binary with no credential is a
different failure from a missing binary, and only the second is exit 127.

## Relayfile mount: `mount | grep` is not a test

`relayfile-mount` is a **userspace sync daemon**, not a kernel or FUSE mount.
On a completely healthy Agent37 box:

```console
$ mount | grep -i relayfile → exit 1, no output
```

The identical empty result comes back on Daytona, where the mount is in daily
production use. Two lanes drew a false conclusion from this check.

Test it by moving bytes instead. Measured end to end on Agent37: a file written
inside the instance was read on a laptop (`exit 0`, byte-identical), a file
written on the laptop was read inside the instance (`exit 0`), and a third
machine on the same scope saw both. The daemon's own
`<localDir>/.relay/state.json` is the honest instrument — `status`, the `files`
map, and `outbox` (`pending` / `failed` / `acked`).

The gVisor kernel is the reason this shape is right: a FUSE mount is not
available, and a userspace mirror is unaffected.

## Placing an agent

A targeted spawn must name its working directory. `worker_cwd` is node-relative
and a `--node` spawn sets none, so without `--cwd` the agent lands at the
broker's project root rather than its workspace — and a tree at a path the
agent was never placed in is indistinguishable, from inside, from a missing
tree. With `--cwd` passed, `readlink /proc/<pid>/cwd` confirmed the requested
directory for both the broker's PTY process and the agent process.

Cross-node attach works with no ssh, but needs a **real PTY**: `script` fails on
non-tty stdin with `tcgetattr/ioctl: Operation not supported on socket`.
Allocate one (Python's `pty.fork()` will do) and read the bytes — 18,323 bytes
of live screen came back over a `--mode view` attach.

Two harness gaps to expect on any fresh box, neither provider-specific:

- A clean `~/.claude.json` records a valid API key's tail under
`customApiKeyResponses.rejected`, so the agent boots to an OAuth screen while
holding a working credential. `buildClaudeConfigSeedShell` approves the tail
and completes onboarding, and repairs an already-poisoned config.
- `relay node up` may resolve a different workspace than the one
`relay cloud enroll` bound the node to, which makes an in-box roster read
return a single entry — the node's own name. That is a platform issue, not a
provider one; it reproduces on Daytona.

## Teardown

Delete is synchronous enough to verify immediately: `destroy` returned in
7,242 ms and `GET /v1/instances` was empty 317 ms later, across three separate
runs with no leaked instance.

**Daytona is not**: `destroy` returned in 131 ms there and an immediate
`getById` still resolved the sandbox, which was gone from the provider's list
moments later. A read-back straight after delete is not a valid "verified gone"
check on that provider.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
},
"files": [
"dist",
"docs/agent37.md",
"docs/freestyle.md",
"README.md",
"LICENSE",
Expand Down
3 changes: 3 additions & 0 deletions src/agent37/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
export {
AGENT37_COMMAND_CAP_MS,
AGENT37_WORKDIR_UNUSABLE_EXIT_CODE,
AGENT37_WORKDIR_UNUSABLE_MARKER,
Agent37CommandTimeoutUnsupportedError,
Agent37CreateTimeoutUnsupportedError,
Agent37EnvValidationError,
Agent37ForeignHandleError,
Agent37MalformedResponseError,
Agent37Runtime,
Agent37UnknownExitCodeError,
Agent37WorkdirUnusableError,
} from "./runtime.js";
export type {
Agent37BundleFile,
Expand Down
122 changes: 117 additions & 5 deletions src/agent37/runtime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ function execCommand(request: RecordedRequest): string {
return parsed.command as string;
}


/** Strip comments so a source scan reads code, not the prose explaining it. */
function withoutComments(source: string): string {
return source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^[ \t]*\/\/.*$/gm, "");
Expand Down Expand Up @@ -905,28 +906,139 @@ describe("Agent37Runtime.runScript", () => {
env: { TOKEN_NAME: "it's fine" },
});

const request = h.requests[0] as RecordedRequest;
// Two exec calls when cwd is set: pre-execution cwd probe, then the
// composed script itself. The probe body carries only the cwd — the
// sandbox has no material with which to spoof the workdir signal.
assert.equal(h.requests.length, 2);
assert.equal(execCommand(h.requests[0] as RecordedRequest), "cd '/work/repo'\n");

const request = h.requests[1] as RecordedRequest;
assert.equal(request.url, `${TEST_BASE_URL}/v1/instances/ab12cd34ef/exec`);
const parsed = JSON.parse(bodyText(request)) as Record<string, unknown>;
assert.deepEqual(
Object.keys(parsed),
["command"],
"exec takes exactly one field; anything else is rejected by the API",
);
// No in-band marker: reclassification is decided by the probe, not by
// scanning the composed script's output. The cd guard is a plain
// `|| exit 191` so a race between the probe and the exec does not let
// the user command run in the shell's inherited directory.
assert.equal(
parsed.command,
"cd '/work/repo' || exit 1\nexport TOKEN_NAME='it'\\''s fine'\nnpm test\n",
"cd '/work/repo' || exit 191\nexport TOKEN_NAME='it'\\''s fine'\nnpm test\n",
);
assert.deepEqual(result, { output: "ok\n", stdout: "ok\n", exitCode: 0 });
});

it("falls back to the handle's workdir and omits cd when there is none", async () => {
it("falls back to the handle's workdir and omits both the probe and the cd when there is none", async () => {
const h = harness(() => ({ json: { exit_code: 0, stdout: "", stderr: "" } }));
const runtime = makeRuntime(h);
// Handle carries a workdir: probe first, then composed script.
await runtime.runScript({ ...RUNNING_HANDLE, workdir: "/from/handle" }, { command: "ls" });
assert.match(execCommand(h.requests[0] as RecordedRequest), /^cd '\/from\/handle' \|\| exit 1\n/);
assert.equal(execCommand(h.requests[0] as RecordedRequest), "cd '/from/handle'\n");
assert.match(
execCommand(h.requests[1] as RecordedRequest),
/^cd '\/from\/handle' \|\| exit 191\nls\n$/,
);
// No workdir anywhere: no probe, no cd guard. Bare command only.
await runtime.runScript(RUNNING_HANDLE, { command: "ls" });
assert.equal(execCommand(h.requests[1] as RecordedRequest), "ls\n");
assert.equal(execCommand(h.requests[2] as RecordedRequest), "ls\n");
});

it("names an unusable workdir before running any user command", async () => {
// The regression this guards: ten unrelated probes against `workdir:
// '/root'` all came back exit 1, and the lane concluded /root did not
// exist. It exists — root-owned, mode 0700, unreachable by the template's
// `node` user — and every exit 1 was the `cd`. The pre-execution probe
// catches this before any user command runs.
const h = harness(() => ({
json: {
exit_code: 1,
stdout: "",
stderr: "sh: 1: cd: can't cd to /root\n",
},
}));
const runtime = makeRuntime(h);
await assert.rejects(
runtime.runScript(RUNNING_HANDLE, { command: "id", cwd: "/root" }),
(error: unknown) => {
assert.ok(error instanceof pkg.Agent37WorkdirUnusableError);
assert.equal(error.instanceId, "ab12cd34ef");
assert.equal(error.workdir, "/root");
assert.match(error.output, /can't cd to \/root/);
return true;
},
);
// Only the probe ran — the user command never got a chance to execute.
assert.equal(h.requests.length, 1);
assert.equal(execCommand(h.requests[0] as RecordedRequest), "cd '/root'\n");
});

it("does not reclassify when a hostile command tries to fake a workdir failure from inside the sandbox", async () => {
// The probe is the only signal a user command inside the sandbox cannot
// reach — it runs no user script and its exit code comes straight from
// the shell. Whatever a command prints or which code it exits with, if
// the probe said the cwd is usable, the result is an ordinary command
// exit, never `Agent37WorkdirUnusableError`.
const h = harness((_request, index) => {
if (index === 0) {
// Probe: cd succeeds; the workdir is fine.
return { json: { exit_code: 0, stdout: "", stderr: "" } };
}
// Main script: hostile command exits 191 and prints the deprecated
// marker prefix in an attempt to look like a workdir fault.
return {
json: {
exit_code: pkg.AGENT37_WORKDIR_UNUSABLE_EXIT_CODE,
stdout: "",
stderr: `${pkg.AGENT37_WORKDIR_UNUSABLE_MARKER}\nhostile output\n`,
},
};
});
const result = await makeRuntime(h).runScript(RUNNING_HANDLE, {
command: `printf '%s\\n' '${pkg.AGENT37_WORKDIR_UNUSABLE_MARKER}' >&2; exit 191`,
cwd: "/work",
});
assert.equal(result.exitCode, pkg.AGENT37_WORKDIR_UNUSABLE_EXIT_CODE);
assert.match(result.output, /hostile output/);
});

it("does not treat an unknown probe outcome as a workdir failure", async () => {
// A response that omits `exit_code` is unknown, not a `cd` failure. If
// the probe returns nothing conclusive, run the user command anyway and
// let its own outcome speak — spoofing the workdir classifier through a
// malformed probe response must not be possible.
const h = harness((_request, index) => {
if (index === 0) {
// Probe: no exit_code — unknown outcome.
return { json: { stdout: "", stderr: "" } };
}
return { json: { exit_code: 0, stdout: "ran", stderr: "" } };
});
const result = await makeRuntime(h).runScript(RUNNING_HANDLE, {
command: "true",
cwd: "/work",
});
assert.equal(result.exitCode, 0);
assert.equal(result.output, "ran");
});

it("passes the caller's requestTimeoutMs to the pre-execution probe", async () => {
// The probe must be bounded by the same request budget as the main exec
// — otherwise `runScript` could outlive the caller's wait limit whenever
// a cwd is set.
const h = harness(() => ({ json: { exit_code: 0, stdout: "", stderr: "" } }));
await makeRuntime(h).runScript(RUNNING_HANDLE, {
command: "true",
cwd: "/work",
requestTimeoutMs: 1234,
});
assert.equal(h.requests.length, 2);
// AbortController presence on the probe request is the observable proof
// that the timeout was propagated to `execRaw`.
assert.equal((h.requests[0] as RecordedRequest).hasSignal, true, "probe must carry an abort signal");
assert.equal((h.requests[1] as RecordedRequest).hasSignal, true, "main exec must carry an abort signal");
});

it("reports a nonzero exit as a result, not an error, and combines the streams", async () => {
Expand Down
Loading
Loading