Skip to main content
Authoring is invite-only private beta. Everything on this page needs an Aethis API key with authoring scopes, plus your own model-provider key for the generation steps. Request access, or start on the open evaluate tier with your first decision — no key required. The two tiers are set out on Capabilities and access.
You are a coding agent. Given source legislation + test cases, you’re producing a deterministic rule ruleset. This is the authoring workflow. Three phases — each gated on the previous. Only phase 3 has a TDD loop today; phases 1 and 2 are informal. Requires an Aethis API key with projects:write and rulesets:write. Set AETHIS_API_KEY in your environment. If you’re using MCP, the key goes in the MCP client config (see MCP install).

Phase 1 — Section discovery

Legislation often covers multiple independent criteria. Split each into its own section so they can be tested and regenerated separately. The two interfaces approach this differently. MCP has an explicit aethis_discover_sections tool the agent calls before authoring. The CLI infers section structure at generate time from the source documents plus any guidance you provide — if you want explicit sections, drop one source file per section into sources/ or add section hints to guidance/hints.yaml.
Authoring is multi-step and tightly stateful (project → sources → fields → generate → publish). The CLI and MCP tools orchestrate this for you. The Python SDK does not yet expose authoring endpoints; the raw HTTP endpoints are listed in the REST API reference for completeness but are not the recommended path.

Phase 2 — Field vocabulary

Define the input fields each section will consume. Shared vocabulary across sections lets rulebooks compose cleanly. The two interfaces approach this differently too. MCP exposes explicit discovery and pinning tools the agent invokes before generation. The CLI infers fields at generate time from your test inputs in tests/scenarios.yaml — the field IDs you write into your tests become the field vocabulary. Use prefixed names (applicant.age, household.income) to keep namespaces tidy across sections.
Field descriptions and enum constraints come from the source text + any hints in guidance/hints.yaml — e.g. applicant.visa_status is an enum with values student, work, settled.”
Phase 2 must be settled before generation starts — fields can’t be renamed freely once rules reference them.

Phase 3 — Rule generation (TDD loop)

The only phase with an automated test gate. Test-first is non-negotiable: write the tests, THEN generate, THEN iterate until green.

Step 3.1 — Write tests

Test cases drive everything — the generator iterates until every test passes, the publish endpoint refuses to ship a ruleset with a failing test, and (for the CLI) the field vocabulary is inferred from your test inputs. The default location after aethis init is tests/scenarios.yaml for the CLI; for MCP-driven authoring, test cases are supplied inline to aethis_create_ruleset or aethis_generate_and_test.

Step 3.2 — Generate

Step 3.3 — Review + refine

Refinement in the CLI is iteration on inputs — there is no standalone refine command. If a test fails:
  1. Re-read the failing case — was the relevant clause in sources/ actually clear?
  2. Add a guidance hint in guidance/hints.yaml, e.g. “The age cap is 65, not 60 — see Section 7.2.”
  3. Re-run aethis generate --poll && aethis test.
Rules compile from the source, not from the tests — so you refine the source text or the hints, never the generated rules.

Step 3.4 — Publish

Only publish when aethis test shows 100% pass. The publish endpoint runs the tests again server-side as a gate.
The aethis/* namespace is reserved for first-party rulesets maintained by Aethis. Use a tenant namespace (e.g. my-team/*, my-company/*) for your own rulesets. See Nomenclature.

Composing sections into a rulebook

Once each section has an active ruleset with a stable slug, create the rulebook. See the worked UK Free School Meals example for a full multi-section composition including the outcome_logic AST.
The outcome_logic must be a proper Expr AST. The server rejects the text shorthand { "expr": "A AND B" } with HTTP 422 at ingress since aethis-core 0.7.2. To find the group names your sections emit, inspect each ruleset’s compiled criteria — or use a known pattern like the one in the FSM example.

Verification checklist

Before declaring a rule complete:
  • aethis test passes 100% on the ruleset that’s about to be published
  • /decide with the published ruleset_id returns the expected decision for each test input
  • If the rule is public-facing, visibility is public (auto-set for aethis/* slugs; use PATCH /rulesets/<id>/visibility otherwise)
  • The ruleset shows up in GET /api/v1/public/rulesets (public) or via the authored key (private)

Next steps