A durable, provider-neutral execution kernel for long-running agents, with a
release-current BytePlus adapter —
specified in memo.md and built out through the full roadmap
(durable kernel, Phase 2 enterprise capabilities, Phase 3 subagents, Phase 5
semantic operations, productionization, and the deferral features). An agent run
is a durable identity and event history whose execution moves across replaceable
workers and sandboxes: it survives worker death, sandbox loss, redeployment,
and long approval waits without losing progress or duplicating irreversible
actions.
Built with the byteplus-cloud skill. The release-current BytePlus claim boundary is the versioned provider-conformance matrix. Historical demonstrations are not release-current verification.
📘 New here? Complete the first durable run. It needs only Docker and no BytePlus credentials. The Usage Guide is the complete API and operations reference; cost is in docs/COST.md.
| Goal | Start here |
|---|---|
| Complete a run without local Node.js or cloud credentials | Tutorials → first durable run |
| Develop or test from source | Getting started |
| Deploy the controlled alpha | Deployment and rollback runbook |
| Integrate a product such as Kertas | Kertas runtime contract |
The public controlled-alpha image is linux/amd64 and anonymously pullable at:
ghcr.io/straits-ai/managed-agents-runtime@sha256:07dcb446d811fa51fb30a7746f55ed72becbbb8b5ad41dfafc6ec8cff9af2440
Release: v0.1.0-alpha.2.
Use the tag for discovery and the digest above for a reproducible deployment.
This repository is the managed execution plane. It owns Managed Sessions, Runs, Attempts, leases, recovery, events, approvals, artifacts, and governed side effects. Kertas owns Projects, interactive Workspaces, knowledge provenance, Outcome Contracts, Releases, Deployments, Routines, connectors, and product UX. The systems integrate only through the runtime's public API and event protocol.
Architecture and release boundaries:
- Kertas product boundary
- Kertas ↔ runtime contract
- Provider portability contract
- Engineering risk register
- Controlled-alpha deployment and rollback
Release status: the automated controlled multi-tenant alpha gate passes for this source revision, and
v0.1.0-alpha.2is publicly available as a controlled alpha. The gate checks the full suite plus named P0 configuration, tenancy, admission, knowledge, HTTP/MCP, credential, concurrency, and crash-recovery assertions, and retains commit-bound JSON evidence in CI. This is a controlled-alpha claim only: the versioned provider matrix limits live claims, while the P1 register and explicit production approval remain open.
POST /v1/runs ──▶ Fastify API ──▶ Postgres (runs, gapless run_events,
attempts+leases, checkpoints, receipts,
approvals, grants, outbox)
▲
worker: claim (SKIP LOCKED) ── heartbeat/fence ── reaper (orphan → requeue)
│
└─ epoch: veFaaS Cloud Sandbox ── restore workspace from TOS
── ModelArk tool loop ── tool router (grants → approvals →
exactly-once receipts) ── checkpoint to TOS ── verify → COMPLETE
- State machine (
src/core/): every transition is one Postgres transaction — row lock, gapless event append, run update, outbox insert — through a single choke point (transitionRun). Waiting states: approval, external signal (wait_for_signaltool ⇄POST /v1/runs/{id}/signals), and delayed start (scheduledFor). - Observability (
src/harness/): every tool call is auditable in the ledger — external writes via receipts (ToolInvocationStarted/Committed), workspace tools viaToolInvokedevents. - Subagents (
src/scheduler/children.ts): a run'sdelegatetool spawns child runs that execute in parallel (each with an isolated copy-on-write workspace seeded from the parent, and a carved share of the parent's token budget). The parent suspends toWAITING_CHILDRENwith zero compute and resumes with the children's outcomes to merge. A child that fails is replaced with a fresh attempt for the same subtask (memo §25, bounded byMAX_CHILD_REPLACEMENTS) before the parent resumes — the replacement lineage is durable (replaces_run_id/replacement_generation) and every swap is aChildRunReplacedledger event. - Scheduler (
src/scheduler/): lease-based claims withFOR UPDATE SKIP LOCKED; heartbeat fencing; a reaper requeues orphaned attempts (bounded byMAX_ATTEMPTS). - Harness (
src/harness/): execution epochs restore the latest checkpoint (workspace tarball + transcript from TOS), run the ModelArk function-calling loop, and checkpoint continuously. Waiting runs hold zero compute. - Side effects (
src/harness/toolRouter.ts): external writes flow through capability grants → human approval (run suspends) → PENDING receipt → execute with idempotency key → COMMITTED receipt. Recovery never re-executes a committed action. - Providers (
src/providers/): the kernel sees only provider interfaces; BytePlus implementations (ModelArk via theopenaipackage, veFaaS sandbox with our own HMAC signer, TOS) are adapters — and so are the local, no-BytePlus ones (src/providers/local/): a child-processLocalSandbox+ filesystemObjectStorelet the whole runtime execute without any cloud dependency (memo §21 portability). - Provider capability selection (
provider-conformance/,deploy/provider-profiles/): versioned model, sandbox, object, event, credential, knowledge, memory, Skill, and MCP contracts declare required, optional, and unsupported semantics. Kertas supplies capabilities and minimum assurance—not a provider brand—and stale or unsatisfied bindings fail closed. Authenticated clients discover and resolve the same checked data throughGET /v1/provider-capabilitiesandPOST /v1/provider-capabilities/resolve. The release-current second-cloud proof is intentionally limited to anonymous, read-only AWS S3; see the portability boundary. - Portability (
src/export/runBundle.ts): a run exports as a self-contained bundle — gapless events, receipts, grants, and the workspace snapshot — so customer execution state is owned and movable across deployments (GET /v1/runs/{id}/export). - Memory (
src/providers/pgMemory.ts): cross-runMemoryProvider— an agent recalls what it learned in earlier runs and writes new memories with theremembertool. Postgres (full-text ranked) by default; the AgentKit Memory binding is a drop-in adapter (MEMORY_PROVIDER=agentkit). - Semantic supervisor (
src/harness/supervisor.ts): a provider-neutral, pure evaluator that watches each run's own durable signals — the sequence of proposed actions, the progress ledger, and the remaining budget — to detect loops, stagnation, context loss, and low budget. It steers a stuck run through a bounded ladder — corrective note → adaptive model routing to a stronger model (src/harness/modelRouter.ts) → definitive terminate — so a run can never spin forever burning budget. State is checkpointed, so detection survives crashes; every decision is a ledger event (LoopDetected,StagnationDetected,ModelEscalated, …). - Multi-tenancy & authorization (
src/api/auth.ts,src/store/tenants.ts): every request authenticates to a tenant — the operator token maps to a built-indefaulttenant, and per-tenant API keys (mak_…, stored only as SHA-256 hashes) map to their own. All run/agent reads and writes are tenant-scoped (a cross-tenant id reads as not-found, never leaking existence), and per-tenant quotas (max_concurrent_runs,daily_token_budget) cap spend. Mint tenants/keys withnpm run admin. - Cost attribution (
src/core/costs.ts,src/store/usage.ts): per-run and per-tenant token/cost rollups atGET /v1/runs/{id}/usageandGET /v1/usage. Seedocs/COST.md— a real run costs ≈ half a cent in model tokens, and durable waits cost zero compute. - Operations (
src/log.ts,src/api/): structured JSON logging, unauthenticated/healthz+/readyz(DB-checked) probes, per-tenant rate limiting (in-process or Postgres-backed cross-instance viaRATE_LIMIT_SCOPE=global), request body limits, and bounded graceful shutdown on the API and worker. - Event streaming (
GET /v1/runs/{id}/events/stream): real-time Server-Sent Events alongside the long-poll endpoint, withLast-Event-IDresume (events are durable, so a reconnect replays with no gap). - Forking (
POST /v1/runs/{id}/fork): branch a new run from a source run's checkpoint + workspace — copy-on-write workspace seed + resume from the source's step, inheriting its progress ledger and grants (src/store/runs.ts). - Event transport (
src/store/outbox.ts,src/bin/relay.ts): every event writes a transactional outbox row; therelayprocess drains it to a pluggableEventPublisher(FOR UPDATE SKIP LOCKED, at-least-once). In-process by default;PUBLISHER=kafkauses the realKafkaPublisher(kafkajs). A historical BytePlus cluster run completed a publish/consume roundtrip, but this release has no current cluster/API-version record (npm run relay). - Credential broker (
src/providers/credentialBroker.ts): per-tenant secrets encrypted at rest, released to a run's outbound tool call only after verifying tenant + action + resource + expiry + call-limit, and injected into the tool adapter — never the model context, tool result, or audit ledger (memo §9.5). Encryption is a pluggableSecretCipher:LocalCipher(AES-256-GCM key in config) orKmsCipher(BytePlus KMS,CREDENTIAL_PROVIDER=kms). Manage withnpm run admin credential ….
npm install
docker compose up -d # local Postgres 16 on :5433
npm run migrate
npm test # full state-machine and integration suite
npm run release:gate # dependency audit + controlled-alpha P0 evidenceThen read the Usage Guide to drive agents through the API.
The versioned image runs as a non-root user and exposes explicit process roles:
docker run --rm --env-file runtime.env \
ghcr.io/straits-ai/managed-agents-runtime:v0.1.0-alpha.2 migrate
docker run --rm --env-file runtime.env -p 8080:8080 \
ghcr.io/straits-ai/managed-agents-runtime:v0.1.0-alpha.2 apiDeploy by the registry digest recorded in the GitHub prerelease, not by tag alone. See the deployment and rollback runbook for role, probe, migration, and rollback contracts.
Copy .env.example to .env and fill it in. Provisioning and credential helpers
live in scripts/. Keep deployment-specific resource IDs in a
private operator inventory rather than committing them to this repository:
| Capability | Classification | Current evidence | Shared-deployment claim |
|---|---|---|---|
| TOS object storage | verified |
byteplus-tos-attestation-56861a83-c502-4814-a17a-ba7e60d3661a at e2665c98cb14 |
Verified for the bounded object operations named in the retained record |
| ModelArk inference | verified |
byteplus-modelark-021784694981398d82d61e1341a38f1d55b18f5893f198bb3a585 at 7c2526d9648a |
Verified for one bounded activated preset-model chat invocation |
| veFaaS private Cloud Sandbox | verified |
byteplus-runtime-sandbox-runtime-903655c at 903655c21fee |
Verified for one bounded private CPU sandbox lifecycle with exact cleanup |
| AgentKit Memory | unavailable |
No release-current live record | No release-current adapter/version record; do not present as currently verified |
| AgentKit Knowledge | unavailable |
No release-current live record | Fail-closed in shared deployments until deployment and tenant bindings are attested |
| Skills and MCP | local-only |
No release-current live record | Local registry semantics only; no BytePlus-hosted Skills or MCP claim |
| Message Queue for Kafka | unavailable |
No release-current live record | No release-current cluster/API-version record; do not present as currently verified |
| KMS credential cipher | unavailable |
No release-current live record | No release-current key/API-version record; do not present as currently verified |
The versioned source and detailed limitations are in
provider-conformance/byteplus.v1.json
and the conformance runbook.
| Setting | How to obtain |
|---|---|
BYTEPLUS_ACCESS_KEY_ID/SECRET/SESSION_TOKEN |
python3 scripts/refresh-creds.py syncs STS creds from bp login (~15 min TTL; rerun before a cloud batch) |
TOS_BUCKET |
scripts/provision-tos.ts (idempotent create plus direct/presigned conformance, bounded failure-path evidence, verified object cleanup, and a versioned provenance record) |
ARK_API_KEY / ARK_MODEL |
activate a model in the console, then scripts/get-ark-key.py --endpoint-id ep-… (key + endpoint id → .env) |
VEFAAS_SANDBOX_FUNCTION_ID |
npm run byteplus:sandbox:provision -- --profile dev --region ap-southeast-1 --name <deterministic-name> --evidence-file <owner-only-path> creates or safely reuses an exact released CPU sandbox application |
SANDBOX_TRANSPORT |
private-webshell by default; set apig only for an explicitly reviewed public gateway deployment |
SANDBOX_GATEWAY_DOMAIN / SANDBOX_GATEWAY_API_KEY |
optional public APIG route for the runtime's AIO REST adapter; private conformance uses secret-isolated WebShell and does not require APIG |
Provisioning notes learned the hard way: sandbox application fields omitted from older CLI help are sent through one structured body and immediately read back; CPU applications omit
InstanceTypebecause BytePlus documents every non-empty value as a specific GPU type; applicationMaxConcurrencyis 10, the documented API minimum, while releaseMaxInstanceremains 1; exact-name resources are reused only after full configuration and stable-revision validation; APIG is a separate public-exposure decision, not a private sandbox prerequisite; the OAuth-backedbplifecycle rejects per-run environment values becausebp --bodyis an argv transport; configure non-secret defaults on the released application and use a credential-isolating provider channel for runtime secrets; private commands return at most 100,000 bytes across stdout/stderr, and the UTF-8 text-file seam is bounded to 100,000 bytes per file;CreateSandboxusesInstanceImageInfo.{Image,Command}(notImageUrl) and inherits the released app image when omitted; the released image is the exact pre-cached SandboxFusion image using its documentedbash /root/sandbox/scripts/run.sh, port 8080, andHOME=/home/tigercontract. Kertas initializes its own workspace directory independently.
Then verify every surface:
npm run preflight # control-plane PASS/FAIL per provider
node --env-file=.env --import tsx scripts/provision-tos.ts \
--evidence-file /tmp/tos-conformance.json # TOS live evidence
node --env-file=.env --import tsx scripts/smoke-ark.ts # ModelArk chat (≤32 tokens)
node --env-file=.env --import tsx scripts/smoke-sandbox.ts # sandbox create→private exec→file r/w→verified terminate
npm run byteplus:sandbox:provision -- \
--profile dev --region ap-southeast-1 --name <deterministic-name> \
--evidence-file /secure/path/sandbox-provisioning.json
npm run byteplus:sandbox:conformance -- \
--profile dev --region ap-southeast-1 \
--function-id <released-sandbox-function-id> \
--application-name <deterministic-name> \
--run-id <non-secret-run-id> \
--evidence-file /secure/path/sandbox-runtime.json # real VefaasSandboxProvider via bp OAuth
npm run byteplus:sandbox:cleanup -- \
--profile dev --region ap-southeast-1 \
--function-id <released-sandbox-function-id> --name <deterministic-name> \
--evidence-file /secure/path/sandbox-cleanup.jsonProvisioning reserves an owner-only pending evidence record before its first
cloud call. The record includes a unique non-secret attempt ID that is also
attached to newly created applications, so an interrupted or eventually
consistent create can be identified without adopting unrelated resources.
Interactive bp login belongs in the operator's normal host browser. Containers
may run these non-interactive checks only after the resulting credentials have
been granted to them explicitly. The current claim/evidence boundary for each
adapter is tracked in
docs/BYTEPLUS-PROVIDER-CONFORMANCE.md.
Run the platform:
npm run api # API on 127.0.0.1:8080 (set API_HOST/API_PORT to override)
npm run worker # harness worker (WORKER_EPOCH=scripted for no-model runs)Beyond the acceptance benchmark, the runtime is exercised across production use cases and capability fundamentals, with every run captured for teaching:
# Production use cases (industry workflows)
node --env-file=.env --import tsx scenarios/run.ts sre-incident # SRE: RCA + gated remediation
node --env-file=.env --import tsx scenarios/run.ts support-refund # Fintech: policy refund, money-movement approval
node --env-file=.env --import tsx scenarios/run.ts invoice-reconcile # AP: invoice↔PO 3-way match
node --env-file=.env --import tsx scenarios/run.ts dep-audit # DevSecOps: vuln audit + security gate
node --env-file=.env --import tsx scenarios/run.ts etl-clean # Data eng: messy-CSV cleaning + schema gate
# Capability fundamentals
node --env-file=.env --import tsx scenarios/run.ts data-analysis
node --env-file=.env --import tsx scenarios/run.ts code-gen
node --env-file=.env --import tsx scenarios/run.ts approval-gated
node --env-file=.env --import tsx scenarios/run.ts doc-processingEach writes a structured result (event timeline, artifacts, receipts, token
usage) to scenarios/results/. Two write-ups are generated from these live runs:
docs/articles/— standalone tutorial articles, one per production use case, each with the real input prompt, the agent’s message-by-message execution (from the TOS-persisted transcript), and the verified output.docs/COURSE-MATERIAL.md— the consolidated course, with cross-cutting teaching on durability, governance, and objective verification.
All nine scenarios completed correctly on the live BytePlus stack (Seed-2.0-lite, ~30–60 s each); the two governed writes each hit the external system exactly once.
npm run bench:survival # 90s approval suspension
npm run bench:survival -- --full-hourOne coding run survives: worker SIGKILL → recovery on a new worker → sandbox killed → workspace reconstructed from TOS → approval suspension with zero active attempts → resume → external write executed exactly once → worker killed immediately after the commit → recovery without duplication → verification → COMPLETED with a gapless event history and TOS-verifiable artifacts. Exit code 0 = Phase 1 accepted.
The dated live runs below are historical demonstrations. They do not substitute for current adapter-level conformance after source, tool, API, or provider changes; consult the provider conformance matrix for the current release gate.
| Milestone | State |
|---|---|
| M0–M3 kernel (schema, transitions, scheduler, API) | ✅ built + tested locally |
| M4 signer + preflight | ✅ built + run against live BytePlus |
| M5–M8 real epoch, receipts, verifier | ✅ built + exercised end-to-end |
| M9 survival benchmark | ✅ PASSED on the live stack (TOS + ModelArk + Cloud Sandbox via APIG), 2026-07-17 — 57-event gapless history, exactly-once external write |
| Controlled multi-tenant alpha | ✅ automated P0 gate: fail-closed configuration, tenant inheritance, atomic admission, knowledge isolation, governed HTTP/MCP, credentials, concurrency, and crash recovery. Machine-readable evidence is retained by CI. This is not a public-beta or production-ready claim. |
| Phase 2A: harden what we own | ✅ tool-level observability, budget-exhaustion enforcement, denied-approval, external signals + scheduled runs — all tested |
| Phase 2 — long-term memory | ✅ cross-run memory: remember tool + auto-recall into context, per-agent scoped, full-text ranked. Postgres is the release-current default behind a provider-neutral MemoryProvider; AgentKit remains selectable but is not release-current live-verified. |
| Phase 2 — AgentKit Memory binding | |
| Phase 2 — Knowledge / Skills / MCP | ✅ Postgres knowledge, registry Skills, and policy-classified registry MCP are implemented. The AgentKit Knowledge adapter is tenant-bound but remains fail-closed in shared deployments until live conformance is attested; AgentKit Skills/MCP remain adapter seams, not live-verified integrations. |
| Phase 3 — managed subagents | ✅ delegate tool → parallel child runs, WAITING_CHILDREN suspend + wake, parent→child budget carving, copy-on-write isolated workspaces. |
| Phase 4 — private deployment & portability | ✅ no-BytePlus local stack (LocalSandbox + FS ObjectStore) runs the full durable workspace cycle; capability-level manifests distinguish supported subsets across local, BytePlus, and read-only AWS S3; run-bundle export (GET /v1/runs/{id}/export). This is subset portability, not semantic equivalence across clouds. |
| Phase 5A — semantic agent operations | ✅ semantic supervisor: loop / stagnation / context-loss / budget-low detection → corrective note → adaptive model routing → definitive terminate (no infinite spins); crash-safe (checkpointed) and fully auditable via events. Unit-tested + live-epoch integration test on the local stack. |
| Phase 5B — subagent replacement | ✅ a failed delegated child is replaced with a fresh attempt for the same subtask (durable lineage, bounded by MAX_CHILD_REPLACEMENTS) before the parent resumes. |
| Controlled-alpha operations | ✅ multi-tenant auth, atomic per-tenant admission, cost attribution + /usage, health/readiness probes, structured logging, per-tenant rate limiting, graceful-shutdown timeouts, and an admin CLI for tenants/keys. Public-beta and production gates remain open. Cost reference in docs/COST.md. |
| Deferrals | ✅ SSE event streaming, run forking, Postgres-backed global rate limiting, outbox relay + EventPublisher, and a credential broker are implemented. BytePlus Kafka and KMS are unavailable as release-current provider claims; historical demonstrations and local/provider-neutral contracts remain documented. |
Built well beyond the original Phase 1 cut: subagents (Phase 3), signals + scheduling, AgentKit Memory/Knowledge/Skills/MCP (Phase 2), the semantic supervisor (Phase 5), multi-tenant auth + quotas + cost attribution (Productionization), and the full deferral sweep — streaming, forking, global rate limiting, the event-publisher relay with a Kafka adapter exercised in a historical BytePlus cluster run (provisioned, publish→consume verified, torn down), and the credential broker with a BytePlus KMS cipher. Those Kafka and KMS have historical demonstrations but remain unavailable as release-current BytePlus claims. Remaining external-infra items: FileNAS, and RocketMQ (the Kafka adapter covers the event-bus case). The KMS cipher requires the KMS service enabled on the account before use.