Interpretations¶
Generates written statements per skill, selecting templates from a versioned library and optionally rewriting them with an LLM in the requested tone.
The same resource also exposes LLM-ready Western interpretation
endpoints. These do not ask the model to calculate astrology. The API
first builds deterministic grounding from Western calculators, then the
LLM writes prose from that JSON. Responses include grounding,
features_used, and sources so clients can audit what backed the text.
Create — POST /v1/interpretations¶
Required scope: interpretations:write
Request¶
| Field | Type | Required | Notes |
|---|---|---|---|
chart_id |
UUIDv7 | yes | Must belong to the caller's tenant. |
locale |
string | no, default "en" |
BCP-47. Only templates with a matching locale are eligible. |
tone |
enum | no, default "corporate" |
One of corporate, coach, plain, vedic_traditional. Only changes wording when use_llm_rewrite: true. |
use_llm_rewrite |
bool | no, default false |
If true, the configured LLM provider rewrites the template body in the requested tone. Subject to the LLM cost cap. |
Response — 201 Created¶
{
"id": "019e32cb-...",
"chart_id": "019e32b5-...",
"locale": "en",
"tone": "corporate",
"statements": [
{
"id": "019e32cb-...",
"skill_id": "resilience",
"template_id": "resilience-strength-high-en",
"kind": "strength",
"locale": "en",
"body": "Stress tolerance is a standout strength...",
"score": 0.80,
"rule_path": ["moon_in_fixed_resilience", "mars_in_fixed_resilience"],
"created_at": "2026-05-16T22:00:00Z"
}
]
}
| Field | Type | Notes |
|---|---|---|
statements[].kind |
strength | recommendation | risk |
Picked by which band the skill score falls into. |
statements[].template_id |
string | Stable id of the template chosen. Useful for the feedback loop. |
statements[].rule_path |
string[] | The ontology rules that produced the underlying score. |
Fetch — GET /v1/interpretations/{id}¶
Required scope: interpretations:read
Returns the same shape as create.
LLM-ready Western natal — POST /v1/interpretations/natal¶
Required scope: interpretations:write
The grounding includes Western summary, aspects, dignities, balance, natal houses, dispositors, and chart patterns.
LLM-ready Western relationship — POST /v1/interpretations/relationship¶
Required scope: interpretations:write
{
"chart_a_id": "019e32b5-...",
"chart_b_id": "019e32d8-...",
"language": "en",
"tier": "standard",
"fresh": false
}
The grounding includes synastry contacts, bidirectional house overlays, composite/Davison context, and score breakdowns.
LLM-ready Western forecast — POST /v1/interpretations/forecast¶
Required scope: interpretations:write
{
"chart_id": "019e32b5-...",
"starts_at": "2026-01-01T00:00:00Z",
"ends_at": "2026-01-31T00:00:00Z",
"language": "en",
"tier": "standard",
"fresh": false
}
The grounding includes transit windows, annual profection, forecast themes, and the progressed lunation cycle at the window start.
LLM-ready response¶
{
"interpretation_type": "western_natal",
"language": "en",
"tier": "standard",
"content": "The chart is led by a strong air signature...",
"grounding": {
"interpretation_type": "western_natal",
"features_used": [
{"name": "western.summary", "kind": "deterministic_feature"}
],
"sources": [
{"name": "/v1/western/charts/{id}/summary", "kind": "api_endpoint"}
]
},
"features_used": [
{"name": "western.summary", "kind": "deterministic_feature"}
],
"sources": [
{"name": "/v1/western/charts/{id}/summary", "kind": "api_endpoint"}
],
"input_tokens": 1200,
"output_tokens": 480,
"latency_ms": 900,
"cost_usd": 0.0021,
"interpretation_id": "019e4b7a-...",
"cached": false
}
Use fresh: true to bypass the LLM interpretation cache. Tier rate
limits, usage accounting, persistence, and cost caps are shared with the
main LLM interpretation layer.
How template selection works¶
For each skill in the talent profile:
- Try
strengthtemplates first — picks the one whose band[min, max]contains the score. - If no strength template matches, try
recommendation. - If still nothing, try
risk. - If the chosen kind has multiple matching templates, sample
deterministically by
(chart_id, skill_id)so two charts with the same score don't see identical text.
If no template matches at all, the skill is omitted from the response.
If every skill is omitted, the use-case returns
NoMatchingTemplate (HTTP 422).
Tone caveat — what actually varies¶
Without use_llm_rewrite: true, the tone parameter is recorded for
audit but the template body is returned verbatim. All four tones produce
the same surface text. This is intentional — templates are stable,
auditable, deterministic. Tone is a styling layer applied by the LLM
rewrite pass.
With use_llm_rewrite: true:
| Tone | Rewrite hint passed to the LLM |
|---|---|
corporate |
"Concise, business-friendly tone suitable for HR reports." |
coach |
"Warm coaching tone, second person." |
plain |
"Plain, jargon-free everyday language." |
vedic_traditional |
"Measured, traditional Vedic-astrologer tone." |
The factual claim (which rules fired, which skill, which kind) is preserved across tones — the LLM is instructed to vary phrasing only, not the underlying content. Any deviation triggers an automatic content-faithfulness check before the rewrite is accepted.
Cost considerations¶
Each use_llm_rewrite: true call generates up to twelve LLM completions
(one per skill template). The router fans these out concurrently and
records every call in the per-tenant cost ledger.
A typical interpretation costs around $0.01–$0.05 depending on which
provider the policy routes to. Set LLM_COST_CAP_PER_HOUR_USD to bound
your spend; the cap is enforced before the first call, not after the
budget overshoots.