Documentation
Guides

heyvm-setup

Heyvm is one of three sandbox backends an agent can run in (tensorlake, vercel, heyvm). It's the only option that gives you a persistent sandbox — one that survives across runs and threads — and it's wired through to all of Flapjack's Remote Control surfaces (HTTP, SDK, MCP).

This guide is operational: how to configure the runtime, how to set the provider on an agent from each surface, and how to verify the round-trip.

When to pick heyvm

You want…Provider
The default — fast, ephemeral, Python-flavoured exectensorlake
A Node 24 microVM that boots quickly and dies with the threadvercel
A sandbox that persists across threads / runs (long-lived dev env)heyvm
To bring your own endpoint (mode: 'custom')heyvm

mode: 'persistent' requires provider: 'heyvm'; the UI enforces this.

Runtime configuration

Set in the Flapjack runtime environment (Vercel project env, or local .env.local):

VariableRequiredNotes
HEYVM_API_KEYyesAPI key for https://server.heyo.computer. Issued from the Heyo dashboard.
HEYO_API_KEYdeprecatedRead as a fallback if HEYVM_API_KEY is unset. The adapter logs a warn and continues. Will be removed in a future release.

Local-dev fallback: if neither env var is set, the adapter reads the JWT from ~/.heyo/token.json (created by heyvm login). This is a convenience for running Flapjack locally; production should always use HEYVM_API_KEY.

Setting the provider on an agent

Four ways, all hit the same PUT /api/agents/:id/computer endpoint:

1. UI

Open the agent's settings → Computer → provider dropdown → pick heyvm. Persisted to agent_computer_config.provider.

2. HTTP

curl -X PUT "$BASE/api/agents/$AGENT_ID/computer" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "provider": "heyvm",
    "mode": "persistent",
    "scope": "agent",
    "sizeClass": "small"
  }'

3. SDK (@flapjack/sdk)

import { FlapjackClient } from '@flapjack/sdk';

const client = new FlapjackClient({ apiKey, baseUrl });
await client.updateAgent(agentId, {
  computer: {
    enabled: true,
    provider: 'heyvm',     // 'tensorlake' | 'vercel' | 'heyvm'
    mode: 'persistent',
    scope: 'agent',
    sizeClass: 'small',
  },
});

The provider field is typed as ComputerProvider ('tensorlake' | 'vercel' | 'heyvm') on both ComputerConfig (read) and UpdateComputerConfig (write).

4. MCP (flapjack_update_computer_config)

Available to any LLM connected via Flapjack's MCP server:

{
  "name": "flapjack_update_computer_config",
  "arguments": {
    "agentId": "agt_…",
    "enabled": true,
    "provider": "heyvm",
    "mode": "persistent",
    "scope": "agent",
    "sizeClass": "small"
  }
}

The provider field is optional — if omitted, the server defaults to tensorlake. The MCP schema lists all three valid values so an LLM can pick the right one from the description.

Verification

After flipping an agent to heyvm, run a real exec to confirm the end-to-end path is live:

# Start a sandbox and exec a command via Flapjack's Remote Control.
curl -X POST "$BASE/api/agents/$AGENT_ID/computer/exec" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"command": "uname -a"}'

Expect a 200 SSE stream emitting exec_started, stdout, exit events.

/computer/exec does not create sandboxes — it requires an already-bootstrapped agent-scoped sandbox row in thread_sandboxes. If you get 409 SANDBOX_NOT_READY, the agent hasn't been bootstrapped yet: call POST /api/agents/from-template first (or wait for the existing bootstrap run to finish — watch progress via GET /api/agents/:id/computer/bootstrap/stream).

Lifecycle

The bootstrap flow is the only thing that provisions a sandbox today. There is no separate /computer/deploy endpoint:

ModeProvisioningAcross runs
ephemeralFirst computer.run tool call inside an agent invocation creates a sandbox keyed on (agentId, threadId) via the internal /computer/run routenew sandbox per thread
persistent (heyvm only)POST /api/agents/from-template runs runBootstrap, which creates one heyvm sandbox keyed on agentIdevery thread reuses the same sandbox
customCaller stands up an HTTP endpoint themselves and stores its URL/auth in agent_computer_config.settings (no sandbox is created Flapjack-side)reuses the same external endpoint

Cleanup:

  • The computer-idle cron stops heyvm sandboxes whose last_used_at is older than 2 hours (configurable). It does not delete the thread_sandboxes row — the next exec will resume the sandbox.
  • There is no public DELETE route on /api/agents/:id/computer today. To force-destroy a heyvm sandbox, use the heyvm dashboard or heyvm CLI directly. Heyvm's own TTL (set on the sandbox at deploy time) is the long-tail cleanup.

Cost / billing

Heyvm bills the Heyo account that owns the HEYVM_API_KEY. Flapjack's cost_events table records each exec for org-level visibility but does not reprice it.

Troubleshooting

SymptomCause
SANDBOX_AUTH_FAILED (401) on any heyvm routeHEYVM_API_KEY missing or revoked. Check the Vercel project env.
SANDBOX_UNREACHABLE (502) on every heyvm callserver.heyo.computer is having an outage; not actionable on our side.
HEYO_API_KEY is deprecated; rename to HEYVM_API_KEY warn logYou set the legacy var. Rename to HEYVM_API_KEY in Vercel env.
409 SANDBOX_NOT_READY from /computer/execThe agent has no bootstrapped sandbox yet (thread_sandboxes row missing/destroyed). Call POST /api/agents/from-template to bootstrap, or wait for the in-flight bootstrap run to finish.
Migration 059_rename_heyo_to_heyvm.sql fails on applyA 'heyo' row violates the new CHECK constraint. The migration handles this by dropping the old constraint first; if you still hit it, run SELECT DISTINCT provider FROM agent_computer_config UNION SELECT DISTINCT provider FROM thread_sandboxes; to inspect.
  • lib/sandbox/adapters/heyvm.ts — adapter, uses @heyocomputer/sdk
  • lib/sandbox/registry.ts — provider lookup
  • lib/computer-resolve.ts — agent-scoped sandbox resolution
  • lib/computer-bootstrap-runner.ts — the bootstrap flow that actually provisions the heyvm sandbox
  • app/api/agents/[agentId]/computer/route.ts — GET/PUT computer config
  • app/api/agents/[agentId]/computer/exec/route.ts — public exec (SSE)
  • app/api/agents/[agentId]/computer/status/route.ts — public status probe
  • app/api/agents/[agentId]/computer/bootstrap/stream/route.ts — bootstrap log stream (SSE)
  • app/api/agents/from-template/route.ts — provision-on-create flow
  • app/api/internal/computer/{run,read-file,write-file,sandbox}/route.ts — internal runtime surface (called by Tensorlake)
  • app/api/cron/computer-idle/route.ts — idle cleanup
  • supabase/migrations/059_rename_heyo_to_heyvm.sql — provider-name migration
Docs last updated May 11, 2026