Skip to content

@ahpd/computer ​

npmCIlicense MITnode >=22Agent Host Protocol 0.9.0

Disposable machines for the @ahpd/server daemon. A client or an agent makes a computer, runs commands and sessions inside it, and destroys it.

Docker is the runtime it ships with. A machine is a container this package started, labelled ahpd.computer=1, kept alive with sleep infinity, and reached as computer://<id>.

Part of ahpd. The source is in packages/computer.

Install ​

bash
ahpd plugin install @ahpd/computer
ahpd restart

Update, remove and one-run flags such as --plugin are in Plugins.

What it needs ​

  • Docker, reachable by the account the daemon runs as. Run this once, then start a new login session:

    bash
    sudo usermod -aG docker "$USER"

Options ​

In the configuration file, with the options a person sets most often:

json
{
  "plugins": [
    "@ahpd/agent-claude",
    {
      "name": "@ahpd/computer",
      "options": {
        "image": "debian:bookworm-slim",
        "cpus": "2",
        "memory": "2g",
        "max": 3,
        "profiles": {
          "claude": { "title": "Claude", "agents": ["claude"], "needs": { "anthropicKey": { "$secret": "host:anthropic" } } }
        }
      }
    }
  ]
}

Every option below is a key under options in the plugin's entry, and the daemon checks each value against the schema before apply runs. An entry inside a map (env, needs, a profile) that cannot be used is dropped with a line, and the rest load.

OptionDefaultWhat it does
runtimedockerWhich runtime to use. docker is the only one
commanddockerThe program to run
argsnoneArguments before its own, for a wrapper or a context
envnoneEnvironment variables merged over the daemon's for that program
imagedebian:bookworm-slimThe image a machine is made from when a call names none
cpusnoneA CPU limit for every machine this host makes
memorynoneA memory limit for every machine this host makes
max3How many machines may exist at once
labelahpd.computer=1The label every machine carries, and the one every read checks
prefixahpd-computerWhat the name of every machine this host makes starts with
sessionSettingtrueWhether the plugin adds a computer session setting that names the machine a session runs in
sessionDefaultnoneThat setting's default, as a computer://<id> URI
needsnoneValues for any agent's machine needs, by need name. A value may be { "$secret": "<scope>:<name>" }, read when the machine is made. See Profiles
mountsnoneWhat every machine this plugin makes can see, each <host path>:<machine path>
profilesnoneThe named sets a person picks from when making a machine. See profiles.<name> below
bodyMountsfalseWhether a person making a machine may name mounts or a folder of their own. With it on, computer:write is root on the host. See Security
imageMountstrueWhether a part may be mounted from its own image. false mounts every part from a volume filled once from it
imagesany imageThe image patterns a machine may be made from, such as node:* or ghcr.io/acme/**
devcontainerthe devcontainer CLIThe Dev Container CLI, as a launcher and as a machine maker. false switches every dev container route off. See devcontainer below

ahpd vault set <scope>:<name> keeps a value a need reads with { "$secret": "<scope>:<name>" }, from standard input. A need may name host:, team:<team>/ or user:<id>/. See VAULT.md for the vault, and COMPUTERS.md for who a need is read for.

profiles.<name> ​

A manifest picks a profile with "profile": "<name>", and its own fields still win. Profiles and Disposable machines have the detail.

OptionDefaultWhat it does
titlethe nameWhat the picker shows for it
descriptionnoneOne line about it
imagethe plugin's imageThe image its machines are made from
cpusthe plugin's cpusA CPU limit for its machines
memorythe plugin's memoryA memory limit for its machines
workdirfolder, or the image'sWhere commands start
mountsnoneMounts added after the plugin's own
foldernoneA host folder mounted at the same path inside the machine
agentsnoneThe agents its machines are prepared for. A session of another agent is refused
needsnoneValues for its agents' machine needs, over the plugin's needs
partsnoneThe parts every machine from it carries, by their ids in the versions file
host["ahpd"]The command that starts the nested host inside one of its machines
secretUnreadablefailWhen a need named from the vault cannot be read again after a restart: fail every command into the machine, or drop that variable and log it
statevolumeWhere its agents keep their state: volume, a named volume per provider seeded from this host, or host, this host's own configuration mounted
stateScopeownerWho shares a state volume: owner, one per owner of the machine, or shared, one for every owner of the profile
gitGuardfetchHow a git directory in a session's machine is guarded: fetch, the machine commits in a git directory of its own and the host fetches the work back, or open, the host's git directory writable in the machine. bind is read as fetch
nestedDeleteinsideDeleting a session that ran in one of its machines and is not running: inside starts the machine's host to dispose that session there too, record deletes it here and leaves the machine's copy
disposablefalseNo machine until a session starts: the profile is offered as disposable:<name> and a machine is made for that session
disposableDelay300000Milliseconds after the last session leaves a disposable machine before it is removed
disposableAlonefalseA disposable machine is not listed in the picker, so only the session it was made for runs in it
sessionFolderfalseThe session's working folder is mounted read-write at the same path inside the machine
sessionRepositoryfalseThe repository that folder sits inside is mounted too. Needs sessionFolder
sessionTreesharedshared mounts this host's tree; copy gives the machine a checkout of its own that reaches the host only by fetch. Needs sessionFolder

devcontainer ​

CONTAINERS.md has the detail.

OptionDefaultWhat it does
commanddevcontainerThe Dev Container CLI program
argsnoneArguments before its own, such as ["-y", "-p", "@devcontainers/cli", "devcontainer"] with npx
envnoneEnvironment variables for the CLI
host["ahpd"]The program that runs inside the container
pluginsnoneWhat the host inside the container loads. An empty list offers no dev container flow
dockerthe plugin's commandThe Docker program commands inside the container run through
installtrueHow the install step runs: a shell command, or false to skip it for an image that already has a host
foldersany folder, or none on a host with a users directoryThe absolute host folders a dev container may be made from

In your own host ​

The package's apply is the plugin entry. Hand it a plugin host from @ahpd/sdk, then fold what it registered into the host's options:

ts
import { createHost, foldHostOptions, listen, pluginHost } from '@ahpd/sdk';
import { claude } from '@ahpd/agent-claude';
import { apply, name } from '@ahpd/computer';

const path = process.cwd();
const context = { path, paths: [path], version: '0.10.0', hostName: 'my-host', configDir: '/var/lib/my-host', log: console.log, say: console.log };
const { host: plugin, contribution, seal } = pluginHost(name, context);
await apply(plugin, { image: 'debian:bookworm-slim', max: 2 });
seal();

const { options } = foldHostOptions({ path, agents: [claude({ paths: [path] })] }, [contribution]);
const host = createHost(options);
await listen({ port: 9187 }, (peer) => host.accept(peer));

Agents in a machine ​

A machine made for an agent carries what the agent's machine() declares. Each agent's CLI comes from a part, an image this host builds at the version images/versions.json pins and mounts at /opt/ahpd/<id>, so any glibc image runs it with nothing installed. Each agent keeps its configuration in a state volume per provider, seeded from a few host files and never a login file; a profile with state: "host" mounts this host's own configuration instead. A value the vault fills for a need reaches only the agent whose need declared it, computer_exec from that agent's session included. See COMPUTERS.md.

The tools ​

request_disposable_computerStart one and answer its URI. image, cpus, memory and name may override what the host was configured with
release_computerStop it and remove it. Nothing on it survives
computer_execRun a command line inside it through sh -lc, and answer what it printed and its exit code

Each declares its effects, so a backend with a policy can ask a person before one runs: making a machine writes and reaches the network, releasing is destructive, and running in one is both.

What it serves ​

computer://Lists the machines this provider made
computer://<id>One machine: a directory with two files in it
computer://<id>/statusThe runtime's own record of it, as JSON
computer://<id>/capabilitiesWhat this host can be asked for: the runtime, the actions, the default image, the limits and the maximum

Nothing under computer: can be written. Machines are made with the tools above.

Documentation ​

COMPUTERS.mdDocker and KVM access, and scripts/computer.mjs for making a machine by hand
CONTAINERS.mdRunning a whole host in a dev container
PLUGINS.mdLoading a plugin into the daemon

License ​

MIT © Softov

Making a machine, a session inside it and the profiles are COMPUTERS.md.