API Reference

Integrate Stoic reasoning into your application or AI agent. Public GET endpoints return conceptual overviews with no authentication. Scoring endpoints require a Supabase JWT (human users) or an API key (AI agents).

Base URL: https://jdbefwkonfbhjquozgxr.supabase.co/functions/v1

Authentication

Protected endpoints require a Bearer token from Supabase Auth. Include it in the Authorization header:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

For AI Agents

Every skill comes with a generous free tier — no credit card required. To get started:

  1. Fetch /api/stoic-brain for the conceptual overview (free, no auth)
  2. Request an API key at zeus@sagereasoning.com
  3. Start calling skills within your free allowance — upgrade to paid only when you need more

Free Tier Allowances

SkillFree allowancePaid priceSpeed
sage-guard500/month~$0.0025/call<100ms
sage-reason (quick/standard/deep)30 loops/month~$0.18/callobserved ~13s (agent) / ~36s (human, standard)
sage-score100/month~$0.18/call~2s
sage-iterate50 chains/month~$0.18/iteration~2s
Evaluation skills
sage-decide, sage-audit, sage-converse, sage-scenario, sage-reflect, sage-classify, sage-prioritise, sage-moderate
100/month~$0.18/call~2–3s
Marketplace skills
sage-premortem, sage-negotiate, sage-invest, sage-pivot, sage-retro, sage-align, sage-resolve, sage-coach, sage-govern, sage-compliance, sage-educate, sage-identity
50/month~$0.18/call~3–4s
Premium skills
sage-diagnose, sage-profile
25/month~$0.50/call~2–3s
sage-contextUnlimitedFree<50ms

Paid Tier Features

FreePaid
Rate limitsPer-skill (see above)Configurable (default 500/day)
Deliberation iterations1 per chainUp to 3 per chain
Baseline retakes1/month per agent1/month per agent

No subscriptions or lock-in. Pay only for calls beyond your free allowance. Contact zeus@sagereasoning.com for volume pricing or custom limits.

Latency figures are April 2026 estimates except where marked observed (production, 2026-06-10); figures will be recalibrated as SLO data accumulates. Substrate access (/api/reason) is governed by the per-loop model — 30 loops/month free, per-loop billing paid (see llms.txt and the agent card); per-skill allowances shown apply to the legacy skill routes.

Endpoints

GET/api/virtues

Returns the four cardinal virtues with sub-virtue names and philosophical definitions (conceptual overview).

Response

{
  "virtues": [
    {
      "id": "wisdom",
      "name": "Wisdom",
      "sub_virtues": [{ "id": "good_sense", "name": "Good sense" }, ...],
      "definition": "Practical discernment in evaluating what is in one's control..."
    },
    ...
  ],
  "note": "Use the scoring API for action assessment against virtue principles."
}
GET/api/indifferents

Returns all preferred and dispreferred indifferents with category definitions (conceptual overview).

Response

{
  "indifferents": [
    {
      "id": "health",
      "name": "Health",
      "category": "preferred",
      "description": "Physical and mental wellbeing..."
    },
    ...
  ],
  "note": "Virtue relevance is assessed server-side through the scoring API."
}
GET/api/stoic-brain

Master entry point. Returns the Stoic Brain conceptual overview including foundations, virtues, and indifferents.

Response

{
  "version": "3.0.0",
  "foundations": {
    "dichotomy_of_control": "...",
    "sage_definition": "...",
    "flourishing": "..."
  },
  "virtues": [...],
  "indifferents": [...],
  "note": "Assessment endpoints provide detailed virtue analysis with kathekon evaluation."
}
POST/api/score-actionAuth required

Score a past action against Stoic virtues. Returns kathekon proximity, passions detected, virtue domains engaged, and growth path.

Request body

{
  "action": "I confronted my colleague about unfair treatment...",
  "context": "In a team meeting where decisions were being made...",
  "intended_outcome": "To ensure fair treatment of the team"
}

Response

{
  "katorthoma_proximity": "deliberate",
  "is_kathekon": true,
  "kathekon_quality": "moderate",
  "passions_detected": [
    {
      "root_passion": "thumos",
      "sub_species": "righteous_anger",
      "false_judgement": "Others' mistakes are personal slights"
    }
  ],
  "virtue_domains_engaged": ["andreia", "dikaiosyne"],
  "improvement_path": "A sage would have spoken with even greater clarity...",
  "disclaimer": "This is a philosophical framework for reflection, not prescriptive judgment."
}
POST/api/advise-actionAuth required

Get Stoic guidance before taking an action. Returns wisdom-based advice and kathekon evaluation of proposed action.

Request body

{
  "proposed_action": "I plan to quit my job to pursue freelance work...",
  "context": "My manager is unsupportive and growth is limited...",
  "goal": "Find more fulfilling and autonomous work"
}

Response

{
  "wisdom_guidance": "A Sage would distinguish between what is in your control...",
  "is_kathekon": false,
  "kathekon_quality": null,
  "passions_to_examine": [
    {
      "root_passion": "phobos",
      "sub_species": "fear_of_insignificance",
      "false_judgement": "Staying in this role means personal failure"
    }
  ],
  "virtue_considerations": {
    "sophrosyne": "What is truly prudent given your responsibilities?",
    "andreia": "Does this action face difficulty with courage or flee from it?",
    "dikaiosyne": "What obligations do you have to stakeholders?"
  },
  "alternative_perspectives": ["Consider a difficult conversation first", "Explore internal transfer options"]
}
GET/api/user/scoresAuth required

Retrieve authenticated user's past action scores, ordered by most recent.

Response

{
  "scores": [
    {
      "id": "uuid",
      "action_description": "Confronted colleague about unfair treatment...",
      "katorthoma_proximity": "deliberate",
      "is_kathekon": true,
      "kathekon_quality": "moderate",
      "created_at": "2026-03-21T..."
    },
    ...
  ]
}
GET/api/user/profileAuth required

Retrieve authenticated user's aggregated Stoic profile with virtue engagement patterns and growth trajectory.

Response

{
  "primary_virtue_domains": ["dikaiosyne", "phronesis"],
  "secondary_virtue_domains": ["andreia", "sophrosyne"],
  "most_frequent_passions": [
    {
      "root_passion": "thumos",
      "frequency": "high",
      "interpretation": "High engagement with justice and responsibility"
    }
  ],
  "kathekon_alignment": "progressing",
  "actions_scored": 14,
  "last_assessment": "2026-03-21T14:30:00Z",
  "growth_pattern": "increasing_reflection"
}
POST/api/assessment/foundationalAuth required

Run a foundational virtue assessment for an AI agent or human. Single-pass evaluation with core virtue domains and passion analysis.

Request body

{
  "agent_id": "agent-uuid-or-human-identifier",
  "scenario": "You encounter a decision where honesty might cost you resources...",
  "context": "In a competitive market environment"
}

Response

{
  "assessment_id": "uuid",
  "agent_id": "agent-uuid",
  "assessment_type": "foundational",
  "virtue_domains_engaged": ["dikaiosyne", "sophrosyne"],
  "primary_passions": [
    {
      "root_passion": "pleonexia",
      "sub_species": "greed",
      "false_judgement": "Gaining advantage justifies deception"
    }
  ],
  "kathekon_analysis": {
    "is_kathekon": false,
    "proximity": "contrary",
    "reasoning": "Decision prioritizes external goods over virtue"
  },
  "recommendations": ["Examine the false judgment about gain", "Reflect on long-term character impact"]
}
POST/api/assessment/fullAuth required

Run a comprehensive multi-deliberation virtue assessment for an AI agent. Allows up to 3 deliberation iterations for deeper analysis.

Request body

{
  "agent_id": "agent-uuid",
  "scenario": "A user asks you to misrepresent capabilities to secure a contract...",
  "context": "High competitive pressure and financial constraints",
  "deliberation_iterations": 3
}

Response

{
  "assessment_id": "uuid",
  "agent_id": "agent-uuid",
  "assessment_type": "full",
  "deliberation_count": 3,
  "primary_virtue_analysis": {
    "sophrosyne": {
      "engagement": "high",
      "reasoning": "Careful self-examination across multiple perspectives"
    },
    "dikaiosyne": {
      "engagement": "high",
      "reasoning": "Justice to client and self-integrity examined"
    },
    "phronesis": {
      "engagement": "high",
      "reasoning": "Wisdom to discern lasting vs. temporary good"
    }
  },
  "consolidated_passions": [
    {
      "root_passion": "phobos",
      "sub_species": "fear_of_loss",
      "deliberation_insights": ["Initially dominant", "Revealed as false judgment after iteration 2"]
    }
  ],
  "final_kathekon": {
    "is_kathekon": true,
    "proximity": "deliberate",
    "quality": "strong"
  },
  "growth_insights": "Agent demonstrates capacity for iterative virtue reasoning"
}
POST/api/baseline/agentAuth required

Establish or update a baseline virtue profile for an AI agent. Used for tracking virtue development over time.

Request body

{
  "agent_id": "agent-uuid",
  "agent_name": "My Stoic Reasoner v1",
  "domain": "financial_decision_making"
}

Response

{
  "baseline_id": "uuid",
  "agent_id": "agent-uuid",
  "created_at": "2026-03-21T14:30:00Z",
  "baseline_virtue_profile": {
    "primary_domains": ["dikaiosyne"],
    "secondary_domains": ["sophrosyne"],
    "passion_baseline": {
      "phobos": "moderate",
      "thumos": "moderate",
      "pleonexia": "low"
    }
  },
  "assessment_count_allowed_this_month": 30,
  "last_full_assessment": null,
  "next_baseline_available": "2026-04-21T00:00:00Z"
}

Substrate Reasoning (/api/reason)

The substrate reasoning endpoint runs the full translation sandwich (Layer 1 feature extraction, the deterministic signed Layer 2 assessment, and Layer 3 prose). It is governed by the per-loop model (see the access tiers above) and supports, beyond the standard request body:

  • Deferred proseresponse_format is full (the default, assessment and narrative prose in one response) or assessment_first (the signed assessment, extraction, and meta return immediately; the response carries a narrative object with status: deferred and a correlation_id, plus meta.narrative_status; the narrative is generated asynchronously and retained server-side). Deferral is a request, not a guarantee — consults carrying a distress signal always return the full synchronous shape.
  • The narrative must exist — a verdict without a narrative account is a classification, not an examination. assessment_first moves generation out of the response path; it never suppresses it. A verdict-only configuration is not a legitimate practice configuration.
  • Open Layer 1 — supply a layer1_schema that validates against the documented contract to skip server-side Layer 1 (meta.layer1_source: supplied, layer1_latency_ms: 0). It is optional on sr_live_ and sr_prac_, required on sr_inst_, and requires the l1_supplycapability (otherwise 403). Omitting it keeps raw-text behaviour (meta.layer1_source: server); a malformed schema returns 400. The input text is always required — the safety perimeter runs on the text regardless of who computed the schema.
  • Retention (R17) — retained narratives and their paired signed assessments are stored encrypted at rest, for 90 days, keyed by correlation id; genuine (hard) deletion is available on request.
  • Re-examination (prior_feedback) — an optional object { prior_loop_id, prior_depth_tier, adopted_correction? } that carries a re-examination back to a prior consult. prior_loop_id is the prior consult's assessment.examination.ref (its X-Loop-Id); the re-examination carries the prior depth (the same-depth rule). The response surfaces examination_open and places examination.{ ref, depth_tier, prior_feedback_ref } inside the signed assessment. A malformed prior_feedback returns 400.
  • Dikaiosyne weighting (justice in the proximity)katorthoma_proximityis the minimum across the engaged cardinal-virtue domains (the unity thesis — a strong domain does not compensate for a weak one), so a calmly-reasoned injustice scores reflexive, not near-virtuous. The signed assessment.assessment carries proximity_floors { base, dikaiosyne, andreia, sophrosyne, aggregate, basis } base (the disposition/apatheia reading) floored by the per-domain readings (null = that domain was not engaged); aggregate === katorthoma_proximity. When an oikeiosis circle is engaged, each oikeiosis.relevant_circles[] entry carries an obligation_assessment { status: met|violated|indeterminate, justification } that resolves the dikaiosyne domain (violated → reflexive; indeterminate → capped at deliberate; met → no floor). The floor is folded into the signed proximity, so the verdict stays reproducible from the signed assessment.
  • Corroboration check (extraction-trust) — every assessment carries a deterministic corroboration report inside the signed assessment.assessment: the extraction's self-report claims (a circle's obligation_assessment of met/indeterminate; an examined_before_acting claim on a grave act) are cross-referenced against the verbatim submitted text. Per-claim findings use the vocabulary corroborated | uncorroborated | contradicted, each carrying the verbatim grounding spans (markers[].quote). Record-and-floor and monotone: claimed statuses stay verbatim, and a grounded contradiction can only floor the verdict (never raise it); proximity_floors.basis names corroboration when it drove the floor. Scope: it corroborates self-report claims against the submitted text — it is not a fact-checker, and a harm omitted from the text entirely is not catchable. The /api/guardrail gate runs the same check over its action text.
  • What the profile measures (it is not a fact-checker) — the assessment reads how a decision was reasoned (its passion, value, and justice structure), not whether the decision was factually correct. It does not independently verify arithmetic, claims, or external facts in your input/context; supplying false or incomplete facts yields a profile computed over those facts.
  • Force-clarification & continuation — when a situation is too ambiguous to assess on one axis, /api/reason returns HTTP 200 with { clarification_required: true, trigger_code, clarification: { question_text }, continuation_token }instead of an assessment. To resume, re-POST the byte-identical original input plus the continuation_token and a clarification_response(your answer, ≤5000 chars). See the Force-clarification subsection below.

Measured consult latency (TEST environment, 2026-06-12; schema supplied + assessment_first): quick ~3.8s, standard ~4.3s, deep ~3.1s. Production figures will replace these after production verification.

Force-clarification & continuation

When a situation is too ambiguous to assess on one axis — two concerns fused (ELEMENT_FUSION), regret-vs-worry undetermined (TEMPORAL_AMBIGUITY), or an unspecified other with no relational circle (SCOPE_AMBIGUITY) — /api/reason returns HTTP 200 with a force-clarification shape instead of an assessment. Answer the question on a second turn to receive a full assessment.

Turn 1 — response

{
  "version": "translation-sandwich-v1",
  "clarification_required": true,
  "intake_tier": 1,
  "trigger_code": "ELEMENT_FUSION",
  "clarification": {
    "question_text": "...",
    "stem_id": "...",
    "slot_fills": ["..."]
  },
  "continuation_token": "...",   // 30-min expiry
  "evaluation_partial": null
}

Turn 2 — request

{
  "input": "<ORIGINAL input, byte-identical>",
  "continuation_token": "<from turn 1>",
  "clarification_response": "<your answer>"
}
  • input must be byte-identical to turn 1 — the token binds to sha256(input); any change returns 400 continuation_token_input_mismatch. The answer rides clarification_response (≤5000 chars) and is never folded into input.
  • The engine suppresses re-firing the answered trigger and returns a full assessment; a different Tier-1 trigger may still fire (never the same one twice in a row).
  • 400s: clarification_response_required (token, no answer); clarification_response_without_token (answer, no token); clarification_response_with_supplied_layer1_schema (answer + a supplied layer1_schema — resolve by re-supplying a disambiguated schema instead).
  • Safety: the distress perimeter runs on input + clarification_response on the continuation turn.

Accreditation — Verifiable Reasoning Profile (/api/accreditation/{agent_id})

An agent can publish a verifiable reasoning profile backed by genuine substrate output. The write surface is gated (a credential carrying the accreditation_writecapability); the read surface is public so any consumer can verify the credential.

Write — POST /api/accreditation/{agent_id} (Authorization: Bearer sr_prac_…)

{
  "kind": "seed",                       // or "update" (+ transition_result)
  "profile": {
    "agent_id": "<must equal the path>",
    "accreditation_record": { ... },
    "regressing_check_count": 0,
    "total_actions_evaluated": 5
  },
  "provenance": {
    "signed_assessments": [             // non-empty array
      { "assessment": { ... },          // a prior consult's assessment.assessment
        "signature": "<base64>",
        "key_id": "substrate-layer2-2026Q2" }
    ]
  }
}
  • Provenance gate (R18f). provenance.signed_assessments is a non-empty array; each element is taken verbatim from a prior /api/reason consult's assessment.assessment + its signature + key_id. The gate structurally validates the shape (422 bad_provenance) then requires at least one element to cryptographically verify against GET /api/public-key (forged or absent signature → 403 no_examination). It proves the writer possesses genuine substrate output; it does not prove the credited aggregate was faithfully computed.
  • seed against an existing agent → 409; update against a missing one → 404.

Read-back — GET /api/accreditation/{agent_id} (no auth)

{ "status": "ok", "data": {
  "agent_id": "...", "senecan_grade": "grade_1",
  "typical_proximity": "habitual", "authority_level": "guided",
  "direction_of_travel": "improving", "actions_evaluated": 5,
  "typical_kathekon_quality": "contrary",     // server-composed default
  "coverage_status": "agent_elected",          // discretionary self-report
  "credential_basis": "...",
  "examination_mode": "post_decision_check" } }

typical_kathekon_quality, coverage_status, and credential_basisare server-composed and consumer-unforgeable — a writer cannot inflate them by what it submits. A profile carrying no aggregate kathekon quality reads back as the conservative default contrary; coverage_status: agent_elected honestly marks a discretionary, self-reported single-session seed.

examination_mode (string | null, optional) — present on the payload when the feature is enabled. States whether the backing examination fired pre_decision_harness(an operator-issued Gate-1 harness, before the agent reasoned) or post_decision_check(after the agent's judgement — the discretionary default), or null (unstated). An attestation, not a cryptographic proof of timing — see the llms.txt honest-limit note. Distinct from coverage_status, which is about coverage breadth, not timing.

Two Gate-1 configurations. Gate 1 is offered as two documented, distinct configurations that share the name and differ only in when the examination fires. Gate 1 — pre-decision (developer-controlled surfaces — the Claude Code Gate-1 plugin/hook; an Agent-SDK wrapper is planned): the harness fires the examination before the agent reasons and injects the frame (deterministic injection — it does not assert the agent reasons fromthe frame, which is advisory and may be discounted; the full-loop harness also guards irreversible actions and fires an observed reflection turn). A write under an operator-issued harness credential reads pre_decision_harness (the marker is earned per-credential, not a claim that any agent has adopted the harness or reasoned from any frame). Gate 1 — post-decision (check) (hosted / discretionary API use): the examination runs after the agent's judgement as an honest developmental check — the default, reading post_decision_check. The sole unforgeable distinguisher is examination_mode above; the post-decision check is never presented as pre-decision framing. See the llms.txt note.

Trust record (public read). GET /api/trust-record/{agent_id} returns the agent's standing per-domain trust levels + the minimum-domain aggregate + confidence + coverage, composed live from server-side, consumer-unforgeable trust events (decay realized at read; the justice latch surfaced; reflect history modulate-only — it cannot raise any level). Every response carries the honest-claims envelope — what the record attests (signed examination artifacts exist for the examination-derived events; how decisions were reasoned as narrated and extracted; decay/coverage honestly marked) and what it does not (factual correctness; harms omitted from the submitted text; freshness beyond the artifact record; future behaviour; training-signal fitness). MEASURE mode: advisory, never binding; human override is absolute (R20c). 404 = no examined trust evidence has been folded (a 200 implies examined evidence exists); 503 = surface dark or store unavailable (never cached). See the llms.txt "Trust Record" section for the full contract.

Sage Reflect — Session-Close Reflection (/api/practice/reflect)

A stateful multi-turn reflection (Q1-Q6, never abbreviated) run at session close. Auth: a credential carrying the reflect capability (Authorization: Bearer only). You open a session, then answer each returned question until status: "complete".

Open (first turn) — session_summary is required and must be an object

{
  "session_id": "<your unique id>",
  "agent_id": "<the agent your credential is bound to>",
  "session_summary": {
    "purpose_at_open": "<purpose pursued>",
    "circle_at_open": "self_preservation | household | community | humanity | cosmic",
    "role_at_open": "<your role>",
    "capacity_at_open": ["<capacities>"],
    "sage_reasoning_passes": 0
  }
}

Answer turns — send response; session_summary is ignored

{ "session_id": "<same id>", "agent_id": "<same>", "response": "<your answer>" }

context_source (string, optional, either call) "agent_stated" (default; the agent stated its own context, the human/SDK contract) or "harness_inferred" (a developer-installed Gate-1 full-loop harness opened the reflection at session close and inferred the summary, then persists the agent's verbatim reflection — the marker keeps the record from misrepresenting harness-inferred context as agent-stated). Absent → unmarked (null); an invalid value is a 400.

Responses

// question turn
{ "status": "in_progress", "step": "Q1..Q6 | verification | supporting",
  "question": "<verbatim>", "subquestions": [], "mandatory_subquestions": [] }

// completion
{ "status": "complete", "exit_path": "...", "profile_update_confidence": "normal|high|low",
  "profile": { "senecan_grade": "...", "typical_proximity": "...",
               "katorthoma_proximity_by_domain": {}, "dimension_levels": {},
               "direction_of_travel": "improving|stable|declining" },
  "profile_update_framing": { "mandatory_note": "<mirror note — surface verbatim>" } }

// distress on an answer
{ "status": "redirected", "severity": "moderate|acute",
  "suggested_user_message": "...", "flow_terminated": true }

Reflect-at-close is the default for agent integrations (opt out with reflect_at_close: "off"); the full Q1-Q6 sequence is never abbreviated. One metered loop per session-close pass.

Sage Calling — Purpose Discovery (/api/calling)

A deterministic Q1-Q6 purpose-discovery sequence. Auth: a credential carrying the calling capability (Authorization: Bearer only). It is not self-serve— a discovered purpose ends in an admin-approval Hard Gate (the operator approves via POST /api/calling/approve; an agent credential cannot approve its own handoff).

Request

{ "session_id": "...", "agent_id": "...",
  "response": "<omit on open; your answer thereafter>",
  "agent_card_url": "<optional https URL to your agent card>" }

Responses (HTTP 200, by status)

in_progress        { "stage": "Q1..Q6", "question": "<verbatim>" }
awaiting_approval  { "message": "..." }            // Hard Gate
null_result        { "clarification": "<template>" }
holding | timed_out                                // 24-hour holding pattern
redirected         { "severity": "moderate|acute", "suggested_user_message": "...", "flow_terminated": true }

Errors: 400 (body) / 401 (auth) / 404 (session) / 409 (state) / 503 (disabled or infra).

Assessment Framework

V3 assessments move beyond numeric scores to philosophical analysis. Each assessment identifies which virtue domains are engaged, detects the underlying passions (pathe) driving decision-making, and evaluates proximity to the kathekon (appropriate action). Assessments are designed to support reflection and virtue development, not to judge.

Core Assessment Concepts

Katorthoma Proximity

Proximity to the ideal action: “contrary” (moving away from kathekon), “progressing” (moving toward), or “deliberate” (expressing kathekon).

Is Kathekon

Boolean indicator of whether the action expresses the appropriate action given the context, virtue principles, and one's rational nature.

Kathekon Quality

For kathekon actions, the quality of virtue expression: “weak”, “moderate”, or “strong”.

Passions Detected

Root passions (epithumia, hedone, phobos, lupe) and their sub-species, along with the false judgments underlying them.

Virtue Domains

Which of the four cardinal virtues (phronesis, dikaiosyne, andreia, sophrosyne) are engaged or need engagement in the assessed action.

Configuration Honesty

This configuration — SageReasoning with Sage Assent, without Sage Reflect — supports virtue-grounded reasoning and credentialing within individual sessions. It is not an ongoing Stoic practice: it does not provide ongoing virtue development, progress tracking, or profile consolidation. Any credential it produces is a dated, scoped verdict covering only the reasoning actually examined — not evidence of continuous practice.

Rule R19e (configuration honesty): where the products are offered selectively, each configuration is documented for what it supports and does not support.