- JavaScript 97.6%
- CSS 2.3%
| .codex | ||
| api | ||
| cli | ||
| config | ||
| docs | ||
| ops/postgres/init | ||
| scripts | ||
| shared | ||
| src | ||
| tests | ||
| worker-api | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| .jscpd.json | ||
| AGENTS.md | ||
| compose.yml | ||
| Dockerfile | ||
| eslint.config.js | ||
| index.html | ||
| knip.json | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.js | ||
| README.md | ||
| vite.config.js | ||
| vite.standalone.config.js | ||
OpenSteward
OpenSteward is a local-first agent orchestration workspace. It lets an operator define agents, execution configurations, durable documents/artifacts, reusable tools, and engine access for Codex, Claude, Gemini, Cursor, and local collector workflows.
The current app is a React/Vite client backed by the modular api/ service, PostgreSQL persistence, and the worker-api/ Docker execution runtime.
What Is Here
- Agent configuration UI for agents, executions, artifacts, tools, and engine setups.
- Runtime session UI for starting and monitoring agent work.
- Tool setup pages with stored server-side credentials and tool manuals.
- Portable sync bundles for moving local agents, sessions, documents, artifacts, and configuration into another OpenSteward environment.
- Admin/debug APIs for production monitoring without direct database or container access.
Local Development
The supported local stack uses the modular API and worker services from the root Compose file:
cp .env.example .env
Generate two independent random values and paste them into .env as
OPENSTEWARD_CREDENTIAL_KEY and OPENSTEWARD_WORKER_API_TOKEN:
node -e "console.log(require('node:crypto').randomBytes(48).toString('base64'))"
Then start the stack:
docker compose up -d --build
Then open:
- App:
http://localhost:5173 - API:
http://localhost:3010 - Worker API:
http://localhost:3020
This starts:
app: Vite client, proxied toapi.api: modular API and PostgreSQL database.worker-api: worker API plus isolated Docker daemon for execution runs.
Useful commands:
docker compose restart api
docker compose logs -f api
docker compose down
If you run the modular API directly on the host while using the Compose database, set the database name explicitly:
$env:DATABASE_URL='postgres://opensteward:opensteward@localhost:55420/opensteward'
npm run dev:api
The full execution runner path is easiest through Compose because api talks to worker-api, which owns the isolated Docker runner.
Node Commands
npm install
npm run dev:client
npm run dev:api
npm run build
npm run test:run
Install the managed-agent CLI from this checkout:
npm link
opensteward agents
opensteward chat <agent-key>
Use opensteward run <agent-key> "..." for a one-shot, scriptable turn and
opensteward resume <session-id> to continue the same managed session. See
Use Managed Agents From The CLI.
npm run lint currently scans some non-app/generated areas too; prefer targeted lint while that is being cleaned up, for example:
npx eslint src/App.jsx src/lib/api.js
Important Environment Variables
DATABASE_URL: PostgreSQL connection string. Compose sets this to the API database service.PORT: API port, defaults to3000.VITE_API_PROXY_TARGET: Vite dev proxy target, defaults tohttp://127.0.0.1:3010; the Docker app service points at the Composeapiservice.OPENSTEWARD_API_RUNTIME_DIR: modular API runtime workspace directory, defaults toruntime.OPENSTEWARD_WORKER_API_URL: worker API URL used byapito dispatch executions.OPENSTEWARD_CORS_ORIGINS: optional comma-separated exact browser origins for split-origin deployments. Same-origin requests need no CORS entry; wildcard access is never the default.OPENSTEWARD_WORKER_API_ALLOWED_URLS: optional comma-separated list of additional exact Worker API base URLs. An origin-wide wildcard is not accepted.OPENSTEWARD_WORKER_API_TOKEN: random deployment-owned bearer token shared only by the API and Worker API. It must contain at least 32 bytes.OPENSTEWARD_WORKER_DISPATCH_CLIENT_TIMEOUT_MS: maximum API wait for the Worker API to prepare and claim a worker session, defaults to1800000(30 minutes).OPENSTEWARD_WORKER_DISPATCH_STALE_BUFFER_MS: safety buffer added before an unclaimed worker dispatch is eligible for orphan reconciliation, defaults to300000(5 minutes).OPENSTEWARD_ORPHANED_WORKER_EXECUTION_STALE_SECONDS: requested orphan threshold, defaults to300; positive values are clamped to at least the worker dispatch timeout plus its stale buffer.OPENSTEWARD_AGENT_TURN_TIMEOUT_MS: maximum model turn duration used by both the API and Worker API, defaults to3600000(60 minutes). Configure the same value for both services.OPENSTEWARD_CREDENTIAL_LOCK_WAIT_TIMEOUT_MS: maximum API wait for another replica to release an agent-engine credential lock, defaults to2100000(35 minutes).OPENSTEWARD_WORKER_TRACE_SYNC_CLIENT_TIMEOUT_MS: maximum API wait for post-turn worker trace and artifact finalization, defaults to1800000(30 minutes).OPENSTEWARD_WORKER_RUN_WORKSPACE_DEADLINE_MS: aggregate worker deadline for persisting one run workspace, defaults to120000(2 minutes).OPENSTEWARD_WORKER_RUN_WORKSPACE_MAX_BYTES: maximum aggregate bytes persisted from one run workspace, defaults to67108864(64 MiB).OPENSTEWARD_WORKER_RUN_WORKSPACE_MAX_ENTRIES: maximum aggregate files and directories persisted recursively from one run workspace, defaults to256.OPENSTEWARD_SESSION_ENVIRONMENT_IDLE_TIMEOUT_MS: managed session environment inactivity limit, defaults to3600000(1 hour). Agent work and real session UI interaction renew the lease; passive status polling does not.OPENSTEWARD_SESSION_ENVIRONMENT_REAPER_INTERVAL_MS: how often the API checks for expired managed environments, defaults to60000(1 minute).OPENSTEWARD_WORKER_EXECUTION_WORKSPACE_RETENTION_MS: retention for inactive worker execution workspaces, defaults to21600000(6 hours).OPENSTEWARD_WORKER_EXECUTION_WORKSPACE_MAX_BYTES: total worker execution workspace budget, defaults to2147483648(2 GiB). Oldest inactive work is removed first; active work is never removed to satisfy the budget.OPENSTEWARD_WORKER_BUILDKIT_KEEP_STORAGE: Docker BuildKit cache budget, defaults to2GB. Shared content-addressed layers remain reusable across sessions within this bound.OPENSTEWARD_RUNTIME_PREVIEW_ENABLED=1: explicitly enables the experimental runtime proxy. It is off by default. When enabled, the worker automatically registers only artifact-requested ports that Docker confirms are published by a running container owned by the same execution and session.OPENSTEWARD_RUNTIME_PREVIEW_MAX_RESPONSE_BYTES: maximum buffered upstream response accepted by the runtime proxy, defaults to33554432(32 MiB) and is capped at 100 MiB.OPENSTEWARD_CREDENTIAL_KEY: deployment-owned key used to encrypt stored credentials. Production rejects missing, short, and published development keys.OPENSTEWARD_ADMIN_API_KEY: protects admin/operator routes.OPENSTEWARD_SYNC_API_KEY: protects sync import/export routes.OPENSTEWARD_SYNC_ALLOW_TOOL_SECRETS=1: allows sync export of tool secrets only when the request also opts in.OPENSTEWARD_PUBLIC_APP_URL: exact public application origin used by OAuth and setup flows.
Keep an existing OPENSTEWARD_CREDENTIAL_KEY for as long as any credential rows were encrypted with it. Replacing or losing the key makes those AES-GCM records undecryptable; the current release does not provide automatic key rotation. Restore the old key or deliberately re-enter credentials before switching keys. The Worker API token is independent and can be rotated by updating the API and Worker API together, then restarting both services.
Managed deployment trust model
The managed API is currently a trusted single-operator control plane. It does not provide end-user identity or RBAC. Keep it on loopback or a private network behind operator authentication; do not expose ports 3010 or 3020 directly to untrusted clients. CORS limits which browsers can read responses, but it is not authentication. Multi-user or public deployment requires a separate identity/RBAC milestone.
Generated HTML/XHTML/SVG previews are intentionally static: scripts, form submission, and outbound connections are blocked. Runtime application preview is disabled by default. Restoring interactive previews safely requires a dedicated cookie-less preview origin and worker/container-bound grants.
Sync API
OpenSteward can export portable JSON sync bundles for moving local agent/session work into another OpenSteward environment.
GET /api/sync/agents/:id/exportexports an agent, its configuration, documents, and sessions.GET /api/sync/sessions/:id/exportexports the owning agent configuration plus one session.POST /api/sync/importimports a bundle into the target environment, preserving UUIDs so repeated syncs update the same records.
Useful query parameters:
include_sessions=falseexports only agent configuration.session_ids=<uuid>,<uuid>limits an agent export to selected sessions.include_documents=falseomits document file payloads.include_artifact_files=falseomits artifact file payloads.dry_run=1on import validates and summarizes the bundle without writing.
Set OPENSTEWARD_SYNC_API_KEY in the target environment to require an app-level key for all sync import/export routes. Clients can send it as either:
Authorization: Bearer <key>
or:
X-OpenSteward-Sync-Key: <key>
Tool credentials are redacted by default. To export stored tool secrets, both the request query include_tool_secrets=true and server environment variable OPENSTEWARD_SYNC_ALLOW_TOOL_SECRETS=1 must be set. Active local runtime state is made inert on import: running sessions become waiting_for_user, active execution runs become cancelled, and active generator sessions become stopped.
Standalone Agent Export
GET /api/v1/agents/:id/export returns a secret-redacted standalone runtime manifest for one agent. It is intended for runners outside the OpenSteward control plane, not for sync/import between OpenSteward environments. Run or inspect a manifest with npm run standalone:agent -- run --manifest agent.json --message "...". See docs/standalone-agent-export.md.
Use npm run standalone:agent -- bundle --agent-id <id> --out-dir ./agent-standalone to create a self-contained standalone agent folder for another repo. The bundle includes agent.json, the browser client, a local runner backend, Docker config, and SQLite session storage; it does not need OpenSteward or the OpenSteward API after export.
Tool Library API
OpenSteward can reuse agent-owned tools without sharing credentials between agents.
GET /api/tool-library/toolssearches tools across agents and returns source agent, linked execution context, run count, last-used time, source import type, and non-secret tool configuration.POST /api/tool-library/tools/:id/copycopies one tool into a target agent.
Useful query parameters for search:
query=<text>matches tool name, source agent, type, env vars, description, and instructions.tool_kind=<kind>filters by tool type.agent_id=<uuid>limits results to one source agent.include_archived=1includes archived tools.limit=<number>caps results, up to 120.
Copy request body:
{
"target_agent_id": "<agent uuid>",
"mode": "copy_configuration"
}
Use mode: "copy_configuration" to reuse install/setup/verify commands, instructions, env var names, JSON config, and source import rules. Use mode: "fresh_configuration" to create the same tool kind from defaults with new configuration. Stored token values, OAuth secrets, cookies, and browser state are never copied.
Admin API
Set OPENSTEWARD_ADMIN_API_KEY to protect operator/debug routes. If it is not set, OpenSteward falls back to OPENSTEWARD_SYNC_API_KEY; if neither key is set, admin routes are open for local development.
Clients can authenticate with:
Authorization: Bearer <key>
or:
X-OpenSteward-Admin-Key: <key>
The admin API is intentionally structured JSON rather than raw SQL:
GET /api/admin/statusreturns app version, build/runtime settings, limits, and key configuration booleans.GET /api/admin/diagnosticsreturns DB/storage health, queue counts, engine setup state, recent errors, and recent admin audit events.POST /api/admin/diagnostics/runruns diagnostics and can refresh engine metadata.GET /api/admin/sessions/:id/debugreturns the full session debug snapshot: config, messages, events, runs, artifacts, artifact versions, documents, evaluations, and checklist items.GET /api/admin/execution-runslists runs with optionalsession_id,status, andlimitfilters.GET /api/admin/execution-runs/:id/debugreturns one run with related session/config/events/artifacts/evaluations and optionalinclude_logs=1.GET /api/admin/execution-runs/:id/logsreturns runner logs.POST /api/admin/execution-runs/:id/cancelmarks a non-terminal run as cancelled.POST /api/admin/execution-runs/:id/retryqueues a retry using the same execution configuration.GET /api/admin/agents/:id/configreturns the full agent configuration.PATCH /api/admin/agent-tools/:idupdates a tool using the same payload shape as/api/agent-tools/:id.POST /api/admin/sessions/:id/context-document/refreshrebuilds session context documents.GET /api/admin/session-artifacts/:id/historyand/downloadinspect artifacts.GET /api/admin/documents/:id/downloaddownloads stored documents.
Admin mutations write to admin_audit_events.
Documentation Map
docs/README.md: documentation entry point split into tutorials, how-to guides, reference, and understanding.docs/tutorials/: guided first-time paths for building, evaluating, repo-managing, and model-comparing agents.docs/how-to/: task-oriented guides for local runs, tools, executions, imports, standalone exports, debugging, and model changes.docs/reference/: technical contracts for source tree, API, data model, sessions, executions, artifacts, tools, definitions, evaluations, and standalone runtime.docs/understanding/: architecture explanations for lifecycle, managed/standalone, repo-managed agents, evaluations, and security.docs/new-agent-development.md: older single-page guide for building and maintaining agents.docs/agent-configuration-plan.md: current agent/execution/artifact configuration model.docs/agent-runtime-runner-plan.md: runtime and Docker runner design.docs/standalone-agent-export.md: standalone agent export manifest contract.docs/codex-engine.md,docs/claude-engine.md: engine setup notes.docs/gmail-oauth-tools.md: Gmail OAuth tool setup.docs/tool-manual-artifacts.md: durable tool manuals.docs/tekton-fluxcd.md: production build/deploy flow.