ADR-0005: Skills are authored via a form, not as code
- Status: accepted
- Date: 2026-05-27
- Refined by: ADR-0009 — the
systemPromptfield referenced below has since been replaced with structuredstrategy: { entry, exit, riskManagement }fields. The form-first decision stands; the shape of one field changed. - Refined by: ADR-0019 — the authoring surface moved from a 7-tab form to a chat agent that writes the same
SkillPayload. The "Skill is data, validated by zod" core of this ADR is preserved; only the input UX changed.
Context
A Skill is a structured configuration: model id, system prompt, whitelisted tools, risk caps, schedule, context settings. Two authoring patterns are possible:
- Code-first — Skill is a TypeScript file in a repo (or in a sandboxed editor); user writes
export default defineSkill({...}) - Form-first — Skill is a database row, edited via a structured web form with field-level validation
The target audience (quants, traders) skews toward strategy intuition + market knowledge, not toward production TypeScript. Friction in iteration cycle = fewer experiments = worse strategies.
We also need every Skill to be guaranteed-valid (zod-conforming), because the same Skill is consumed by sim, live runner, and chat agent — a syntactically broken Skill would crash all three.
Decision
Skills are authored via a structured web form. Submitted Skills are validated with zod and stored as a jsonb row in skill_versions. There is no code authoring path in MVP.
A future optional "deterministic helpers" hook (Phase 4) will let advanced users add entry.ts / exit.ts helpers that the agent loop can call — but the Skill core remains form-defined.
Alternatives considered
Alt A — Code-first Skill files
- Maximum flexibility
- Higher iteration friction for quants
- Requires a code editor surface, syntax errors, lint integration
- Not picked: our users will be writing the strategy in the prompt; that's the high-leverage activity. Everything else is config — config wants a form.
Alt B — DSL (custom strategy language)
- Power-user delight
- Years of investment to do well
- Not picked: we'd be building a programming language instead of a product.
Alt C — Hybrid (form for config, code for prompt)
- The prompt textarea in the form IS the "code"
- This is essentially what we're doing — calling it "form" because everything around the prompt is structured fields
- (Picked, framed differently)
Consequences
Positive
- Iteration speed: quant changes a risk cap, hits Save, runs Backtest — no build, no deploy, no syntax errors
- Guaranteed valid: form validation + zod = every saved Skill is structurally correct
- Versioning is automatic: every Save creates a new
skill_versionsrow; full audit trail - No code execution surface to secure — Skills are pure data
- Marketplace-ready: Skills are content-addressable JSON blobs; trivially shareable / forkable
Negative / trade-offs
- Users can't express logic that isn't expressible as "prompt + tool calls + risk caps"
- Adding new Skill capabilities requires a schema migration + form update + runtime update — not just docs
- Power users may find the form constraining; they'll ask for code escape hatches (anticipated; Phase 4 addresses)
Things we'll need to revisit
- When users demand deterministic helpers (e.g., "always exit if 7-day high broken"), introduce optional
entry.ts/exit.tshooks. Keep the agent loop in charge; helpers are advisory. - If we add an SDK or CLI for power users to manage Skills programmatically, it should still produce the same JSON payload — the form and the SDK both target the canonical schema.
References
docs/architecture/agent-runtime.mdpackages/skill-schema/(when scaffolded)- ADR-0006 — split into trading vs chat agents (relies on Skill being declarative)