Skip to main content
You are a coding agent. You want to answer ‘is this person eligible for X?’ This page is the full sequence. The three-call pattern:
  1. Discover the schema — what fields does the ruleset need?
  2. Collect values — either from user input, context, or an upstream tool.
  3. Decide — send field values, receive a decision envelope.
Optional fourth step: explain — when the decision is not_eligible and the user asks why. Uses the public FSM child-eligibility ruleset. No API key needed.

1. Discover the schema

aethis fields -b aethis/uk-fsm/child-eligibility
The response (same shape across all four interfaces):
{
  "ruleset_id": "aethis/uk-fsm/child-eligibility",
  "slug": "aethis/uk-fsm/child-eligibility",
  "name": "UK FSM Child Eligibility",
  "fields": [
    {
      "field_id": "child.age",
      "field_type": "int",
      "description": "Child's age in whole years at the start of the relevant academic year (1 September).",
      "question": "Child's age in whole years at the start of the relevant academic year (1 September).",
      "weight": 1,
      "enum_values": null,
      "notes": [
        {
          "note_text": "WHY: Free school meals eligibility is tied to compulsory-school-age status, which is determined by the child's age at the start of the academic year.",
          "source": "DfE Free School Meals: guidance for local authorities",
          "metadata": { "type": "why", "section": "child_eligibility" }
        },
        {
          "note_text": "LEGAL BACKGROUND:\n\nCompulsory school age runs from 1 September following the child's 5th birthday to the last Friday of June in the academic year of their 16th birthday. Age is taken as at 1 September of the relevant academic year, not the application date.",
          "source": "Education Act 1996, s.8",
          "metadata": { "type": "legal_background", "section": "child_eligibility" }
        }
      ]
    },
    {
      "field_id": "child.school_type",
      "field_type": "enum",
      "description": "Type of school the child attends.",
      "weight": 2,
      "enum_values": ["state_funded", "independent", "home_educated"]
    }
  ]
}
What the agent needs: a map from field_id → value. For enum fields, only values listed in enum_values are accepted. For int / bool, standard JSON. notes — each field can carry a list of structured FieldNoteOut entries. By convention each note has metadata.type ∈ {"why", "legal_background"} and a source citation. Conversational agents (e.g. an information-gathering paralegal bot) typically surface the WHY:-prefixed note verbatim when a user replies “why?” to a question, and draw on the LEGAL BACKGROUND:-prefixed note for follow-up questions about evidence and edge cases. Older bundles may return "notes": [] — your code should treat the array as optional. weight — higher = less preferred to ask. The decision engine uses this for optimal-path computation when there are multiple ways to satisfy a ruleset (e.g. ask the cheap nationality question before the expensive English-test one).

2. Collect field values

Agent-side logic — the API doesn’t care how you got the values. In practice: ask the user, read from a session object, or derive from upstream context. If a field is missing, the decision can still return (as undetermined) — just be ready to ask for it next.

3. Decide

aethis decide \
  -b aethis/uk-fsm/child-eligibility \
  -i '{"child.age": 10, "child.school_type": "state_funded"}' \
  --explain
All four return the same decision envelope:
{
  "decision": "eligible",
  "fields_provided": 2,
  "fields_evaluated": 2,
  "slug": "aethis/uk-fsm/child-eligibility",
  "ruleset_version": "unknown",
  "engine_version": "aethis-core@0.36.0",
  "decision_id": "dec_...",
  "inputs_hash": "sha256:...",
  "decision_time": "2026-04-19T22:00:00.000Z"
}
Three possible outcomes:
  • eligible — all criteria satisfied
  • not_eligible — one or more criteria failed
  • undetermined — engine couldn’t decide (missing field, discretionary clause, or case outside the compiled rules)
When you get undetermined, inspect missing_fields in the response. Add the missing values and call again. include_trace adds per-group outcomes so you can show the user why.

4. (Optional) Explain the decision

For a not_eligible where the user asks “why”:
aethis decide \
  -b aethis/uk-fsm/child-eligibility \
  -i '{"child.age": 16, "child.school_type": "state_funded"}' \
  --explain
The CLI’s --explain flag calls /decide with trace, then /explain-failure when the outcome is not_eligible, and renders both in one pass.
Returns human-readable reasons for the failure, keyed by criterion, plus a DSL mechanism hint.

Composing multiple sections (rulebook)

If your domain has more than one section and you want one decision over the composition (e.g. FSM: child eligibility AND (household criteria OR universal infant)), use the rulebook_id field instead of ruleset_id. Rulebook evaluation always requires an API key — see Nomenclature for why.
curl -X POST https://api.aethis.ai/api/v1/public/decide \
  -H "Content-Type: application/json" \
  -H "x-api-key: $AETHIS_API_KEY" \
  -d '{
    "rulebook_id": "aethis/uk-fsm",
    "field_values": { ... }
  }'
The response includes a section_results array with each section’s individual outcome.

Next steps