A self-hosted prompt-management platform — DAG editor, canary releases, maker-checker approvals, eval suites, and self-evolution — all powered by Strands Agents.
Promptsheon is a single self-hosted platform that answers one question:
"How do I author a multi-agent prompt, ship it safely to production, prove it doesn't regress, and roll it back if it does?"
It is a Fastify backend on :8080 plus a Next.js web UI on :3000,
talking to a local SQLite file and a content-addressed store. No
cloud account, no signup, no telemetry — pnpm install && pnpm dev
and you have a fully working prompt-management platform with
multi-provider LLM, an audit chain, webhooks, eval scorers, and a
live DAG editor.
For development and contribution work, start with the engineering guide. It documents the clean-architecture boundaries, environment setup, testing strategy, production operation, and the explicit breaking-change policy.
Built on the
@strands-agents/sdk for
every AI call: planning is a 5-agent Swarm, execution is a Graph
of per-node Agents, and standalone Agents handle compilation,
scoring, and self-evolution.
You, even if:
- You've never written TypeScript before.
- You don't know what a "multi-agent DAG" is.
- You've never shipped a prompt to production.
If you can install Node.js and run pnpm dev, you can use
Promptsheon. When the docs use a word you don't know, look it up
in the Glossary
or in AGENTS.md.
If you've used Fastify or Next.js before, you'll be productive in ten minutes.
- DAG-based capability editor — drag-and-drop nodes for Planner, Agent, Tool, and Guardrail; per-node config; live execution preview.
- Releases with canary rollout — versioned releases, per-environment activation, weighted traffic split, and one-click rollback.
- Maker-checker approvals — release creator cannot approve their own release; approvals are persisted with reason and voter.
- Strands-powered planning — a
Swarmof 5 specialised agents decomposes a goal into a capability DAG. - Strands-powered execution — each capability node becomes a
Graphnode with its ownAgent, shared scratchpad, and observability hooks. - Multi-provider LLM — OpenAI, Anthropic, AWS Bedrock, or a custom OpenAI/Anthropic-compatible endpoint. Strands handles retries, timeouts, and structured-output validation.
- Eval suites + scorers — declarative dataset cases, pluggable scorers (LLM-judge, regex, exact-match), and parallel run results.
- Self-evolution loop — monitors live eval scores of an active release; on regression it triggers a re-plan and re-release with cooldown.
- Audit chain — append-only, hash-linked audit log with a cryptographic verification endpoint.
- Content-addressed store (CAS) — every compiled manifest is hashed and stored by content, never by name.
- Maker-checker webhooks — incoming webhooks with HMAC verification and replay protection.
You'll need Node.js 26 or newer and pnpm 11 installed on your computer.
If you don't know what Node.js is or whether you have it:
- Open a terminal (on macOS:
Cmd + Space, type "Terminal"; on Windows: open "PowerShell"; on Linux: open your usual terminal). - Type
node --versionand press Enter. - If you see a version number starting with
26, you're set. - If you see "command not found" or an older version, follow the official Node.js installer guide.
You'll also need at least one LLM API key — OpenAI, Anthropic, or your own OpenAI-compatible endpoint. Promptsheon supports custom-URL providers so a private gateway works out of the box.
Pick whichever option fits your setup:
# 1. Download the code
git clone https://github.com/sachncs/promptsheon.git
cd promptsheon
# 2. Install dependencies for every workspace
pnpm install
# 3. Copy the env template and edit it
cp .env.example .env
$EDITOR .env # fill in OPENAI_API_KEY (or ANTHROPIC_API_KEY)
# 4. Start the backend + the frontend together
pnpm devBy default the backend listens on http://localhost:8080 and the
frontend on http://localhost:3000. No external services beyond
the LLM provider you choose.
💡 The frontend's
next.config.tsrewrites/api/*→http://localhost:8080/api/*automatically. You only need both servers running.
# terminal 1
cd packages
pnpm dev:server # Fastify + tsx watch, :8080
# terminal 2
cd packages
pnpm dev:frontend # Next.js + Turbopack, :3000docker build -t promptsheon:latest .
docker run --rm -p 8080:8080 \
-e OPENAI_API_KEY=$OPENAI_API_KEY \
-v $PWD/.promptsheon:/data \
promptsheon:latestThe image ships a multi-stage build that compiles the shared, server, and frontend workspaces into a single non-root container. It listens on :8080 and serves both the API and the UI from the same port. The audit chain and SQLite database live on the volume you mount at /data.
The fastest way to see Promptsheon work:
# 1. Confirm the backend is up
curl http://localhost:8080/api/health
# {"status":"ok","service":"promptsheon-server", …}
# 2. Open the UI in a browser
open http://localhost:3000 # macOS
xdg-open http://localhost:3000 # Linux
# 3. Walk the wizard:
# - Welcome
# - Admin + org
# - LLM provider (OpenAI / Anthropic / Bedrock / Custom)
# - FinishYou'll land on the control-plane dashboard with a "Create workspace" CTA. From there:
- Workspaces → create a workspace.
- Projects → create a project inside that workspace.
- Capabilities → open the DAG editor (or click one of the templates: Customer support triage, Doc Q&A, Blank canvas).
- Save → the manifest is hashed into the CAS.
- Releases → create a v1 release; cast two non-creator approvals; activate.
That's the full maker-checker loop. Once activated, every
POST /api/executions call routes through that release.
If you'd rather drive the API from your own code, the repo ships a
typed fetch client in frontend/src/lib/api.ts. From a Next.js page
or any TS project:
import { workspaceApi, capabilityApi, releaseApi } from '@/lib/api';
const ws = await workspaceApi.create({ name: 'refund-triage' });
const cap = await capabilityApi.list(projectId);
const release = await releaseApi.transition(releaseId, 'active');
// → 409 APPROVAL_REQUIRED until 2 distinct non-creator approvals
// are on the manifest hash. The gate fires correctly now that
// BaseRepo.findById returns camelCase rows.The full type definitions and request shapes are documented in
packages/server/API.md.
All configuration is via environment variables prefixed with
PROMPTSHEON_. Copy .env.example to .env and edit as needed.
Never commit .env — it is in .gitignore.
| Variable | Purpose | Default |
|---|---|---|
PROMPTSHEON_PORT |
HTTP listen port | 8080 |
PROMPTSHEON_HOST |
Bind address | 127.0.0.1 |
PROMPTSHEON_DB_PATH |
SQLite file path | promptsheon.db |
PROMPTSHEON_CAS_PATH |
Content-addressed store directory | .promptsheon |
PROMPTSHEON_FRONTEND_PATH |
Path to the built frontend | ./frontend/.next |
PROMPTSHEON_CORS_ORIGIN |
Allowed CORS origin | http://localhost:3000 |
PROMPTSHEON_LOG_LEVEL |
Pino log level | info |
PROMPTSHEON_NODE_ENV |
production / development / test |
development |
PROMPTSHEON_AUTH |
Enable JWT bearer-token auth | false |
PROMPTSHEON_JWT_SECRET |
HMAC secret for token verification | "" |
PROMPTSHEON_LLM_PROVIDER |
openai / anthropic / bedrock / custom |
openai |
PROMPTSHEON_LLM_MODEL |
Model id (e.g. gpt-4, claude-3-5-sonnet-20241022) |
gpt-4 |
PROMPTSHEON_LLM_API_KEY_ENV |
Env var holding the API key | OPENAI_API_KEY |
PROMPTSHEON_LLM_MAX_RETRIES |
Strands retry budget | 5 |
PROMPTSHEON_LLM_TIMEOUT_MS |
Per-request LLM timeout | 120000 |
OPENAI_API_KEY |
OpenAI provider key | — |
ANTHROPIC_API_KEY |
Anthropic provider key | — |
AWS_BEDROCK_REGION |
Bedrock region (e.g. us-east-1) |
us-east-1 |
PROMPTSHEON_WEBHOOK_SECRET |
HMAC secret for incoming webhooks — required in production | "" |
PROMPTSHEON_ALLOW_SYSTEM_ACTOR |
Allow X-User-Id: api bypass — off in production |
true (dev) |
PROMPTSHEON_SELF_EVOLVE_ENABLED |
Enable the self-evolution loop | false |
PROMPTSHEON_SELF_EVOLVE_COOLDOWN_SEC |
Min seconds between re-evolves | 900 |
PROMPTSHEON_SELF_EVOLVE_MAX_CONCURRENT |
Cap concurrent evolutions per worker | 3 |
PROMPTSHEON_OTEL_ENDPOINT |
OpenTelemetry OTLP collector URL | "" |
PROMPTSHEON_FIPS_MODE |
Enforce FIPS-validated crypto for the audit chain (requires a FIPS Node build) | false |
PROMPTSHEON_REPLICA_INTERVAL_MS |
Audit-chain replicator poll interval | 5000 |
PROMPTSHEON_REPLICA_ONESHOT |
Replicator exits after a single batch | false |
💡 For a Custom OpenAI/Anthropic-compatible endpoint, set
PROMPTSHEON_LLM_PROVIDER=customand supply the credentials inline during the onboarding wizard (Base URL + API key + Model name). The Settings store persists these per-org.
For everyone:
- CHANGELOG — what changed and when.
- REST API Reference — every endpoint with request/response shapes.
- AGENTS.md — the engineering constitution: type safety, validation, repo layout, testing bar, naming, lifecycle. Read it before opening a PR.
For operators / maintainers:
- CONTRIBUTING.md — how to set up a dev environment and submit changes.
- SECURITY.md — the disclosure policy. Please don't file security issues as public GitHub issues.
- CODE_OF_CONDUCT.md — the standards we expect everyone to follow.
- packages/server/README.md — backend architecture, agent subsystems, hardening layers.
- packages/shared/README.md — domain types, Zod schemas, the SQLite migration runner, the CAS.
| Category | Technology |
|---|---|
| Runtime | Node.js ≥ 26, pnpm 11 workspaces |
| Language | TypeScript (strict, exactOptionalPropertyTypes) |
| HTTP | Fastify 5 |
| Validation | Zod 4 |
| Database | SQLite via better-sqlite3 |
| AI | @strands-agents/sdk — Agent, Swarm, Graph |
| LLM providers | OpenAI, Anthropic, AWS Bedrock, custom OpenAI/Anthropic-compatible |
| Frontend | Next.js 16 (App Router, Turbopack) |
| UI | React 19, shadcn/ui, Tailwind v4 |
| Data fetching | TanStack React Query 5, axios |
| DAG editor | @xyflow/react 12 |
| Icons | lucide-react |
| Observability | OpenTelemetry, Pino |
| Hashing | Node crypto (audit chain, manifest CAS, HMAC) |
| Tests | Vitest 4 (server + shared), Playwright (frontend) |
pnpm install # install all workspace deps
pnpm typecheck # tsc across shared + server + frontend
pnpm --dir packages/server test # vitest, 86 files / 619 cases
pnpm --dir packages/shared test # vitest, 4 files / 36 cases
pnpm --dir frontend test:e2e # Playwright tier suite, 10 specs
pnpm --dir frontend build # next buildTo regenerate the architecture counts above, run bash scripts/stats.sh.
# backend
cd packages/server
pnpm dev # Fastify + tsx watch, :8080
pnpm test # vitest
pnpm build # tsc → dist/
# frontend
cd frontend
pnpm dev # http://localhost:3000 (Turbopack)
pnpm test:e2e # Playwright tier suite
pnpm build # next build
# shared
cd packages/shared
pnpm build # tsc → dist + copies db/migrationsWe use Conventional Commits:
feat: add canary-percent setter on release route
fix: clamp audit-chain hash to 32 bytes
docs: document PROMPTSHEON_WEBHOOK_SECRET
refactor: extract capability-version repo
test: add adversarial eval fixtures
chore: bump @strands-agents/sdk to 1.14
- v0.1.0 — v0.3.0 (shipped) — Fastify + Strands backend, Next.js frontend, DAG editor, releases + canary, maker-checker approvals, audit chain, eval suites, self-evolution loop, webhooks + replay protection, chaos hooks, OpenTelemetry.
- v0.4.2 (current) — admin gates on 14 management routes,
maker-checker gate now fires correctly for self-approvals,
/api/executionsworkflow,/api/goals/:hashdrilldown, DAG editor drafts persist,BaseRepocamelCase mapper, Playwright tier suite rewritten against the new contracts (619 server tests + 41-route smoke + 5 new auth/forms/audit/ manifest-detail/approvals/admin-gating tier specs). - v0.5.0 (next) — Docker packaging shipped
(
Dockerfile+ multi-stage build), production deployment guide, RBAC refinement on the maker-checker flow, dataset import/export. - Backlog — gRPC interface alongside HTTP, multi-tenant SSO, Postgres adapter behind the better-sqlite3 repo layer, Helm chart for Kubernetes, OpenAPI → typed client codegen.
Have an idea? Open a feature request.
Contributions are welcome. See
CONTRIBUTING.md for the process, coding
standards, and Conventional Commits workflow. Bug reports and
feature requests use the issue templates.
The full engineering standards — type safety, validation, repo
layout, testing bar, naming, lifecycle — are codified in
AGENTS.md. Read it before opening a PR.
This project follows the Contributor Covenant v2.1. By participating, you are expected to uphold that standard.
Please do not file security vulnerabilities as public GitHub
issues. See SECURITY.md for the disclosure policy.
The shipped scanner (packages/server/src/security/prompt-scanner.ts)
is exercised by a curated dataset at
docs/security/benchmark/dataset.json
covering OWASP LLM01..LLM10 plus edge cases. Run it with:
pnpm --filter @promptsheon/server bench:security
It writes docs/security/benchmark/RESULTS.md
with a per-case verdict + the rules that fired. CI should gate on a
100% pass rate so a regex tweak never silently regresses coverage.
Government, defense, and regulated customers run on hosts with no
outbound internet. The repo ships an offline installer that bundles
every dependency, the SBOM, and a systemd bootstrap:
bash scripts/build-offline-installer.sh # build the tarball
sudo bash bin/bootstrap.sh --fips # install + FIPS mode
The step-by-step runbook —
docs/operations/air-gap-rhel.md —
covers pre-flight, FIPS-mode requirements, upgrades, backups,
DR, and the FIPS gate's refuse to boot contract.
The firewall sits in front of any LLM application (not just
promptsheon-managed ones) and inspects every prompt + response
against the T2-3 scanner. Block / warn / allow decisions are
written to the audit chain so /api/audit/verify covers sidecar
traffic end-to-end.
# Start the sidecar with an OpenAI-compatible upstream:
PROMPTSHEON_FIREWALL_UPSTREAM_URL=https://api.openai.com \
PROMPTSHEON_FIREWALL_PORT=9090 \
pnpm --filter @promptsheon/server firewallPoint any client at http://127.0.0.1:9090/v1/chat/completions
instead of the upstream URL. The firewall transparently forwards
when the scanner verdict is clean, attaches an
X-Promptsheon-Warning header on warn, and rejects with
422 PROMPT_BLOCKED. The implementation lives at
packages/server/src/firewall/; the policy + scanner extension
shipped with T3-5 carries over unchanged.
packages/sdk/src/integrations/ ships adapters for the three
agent frameworks the doc names. All three route through the
promptsheon OpenAI-compatible gateway so caching + the audit
chain apply transparently.
// Vercel AI SDK
import { openai } from '@ai-sdk/openai';
import { withPromptsheon } from '@promptsheon/sdk/integrations/vercel-ai-sdk';
const model = withPromptsheon(openai('gpt-4'), {
gatewayUrl: 'https://promptsheon.example.com',
apiKey: process.env.PROMPTSHEON_API_KEY!,
});
// LlamaIndex
import { PromptsheonLLM } from '@promptsheon/sdk/integrations/llamaindex';
const llm = new PromptsheonLLM({
gatewayUrl: 'https://promptsheon.example.com',
apiKey: process.env.PROMPTSHEON_API_KEY!,
model: 'gpt-4',
});
// Haystack
import { PromptsheonGenerator } from '@promptsheon/sdk/integrations/haystack';
const generator = new PromptsheonGenerator({
gatewayUrl: 'https://promptsheon.example.com',
apiKey: process.env.PROMPTSHEON_API_KEY!,
model: 'gpt-4',
});The adapters use structural typing (no @ai-sdk/provider,
llama-index-core, or @haystack/core runtime dep) so the SDK
stays framework-optional — install the framework package
yourself and pass a model that satisfies the shape. 9 vitest
cases exercise the wire format against an in-process
OpenAI-shaped stub.
Apache-2.0 © 2026 Sachin — sachncs@gmail.com.