Journey. As a developer, I have a hard question — an analysis, a
comparison, a judgment call — and I want the best answer the platform can
produce within a budget I control. This guide shows the one call that defines
the Chloe surface and the budget knob that shapes every answer.
Chloe is the platform's reasoning surface. You send an OpenAI-compatible chat request; the service decides how much deliberation the prompt deserves, spends it, and returns the answer with a telemetry block recording what the request cost. Like Bella (guide G-20), Chloe is stateless one-shot: every call is self-contained — the service creates a fresh, single-use model session for the call and discards it afterwards. There is no session id, no history, and nothing to clean up.
Concepts (only what this journey needs)
- The effort knob is the product.
effort(fast,balanced,deep,
maximum, default auto) states how much deliberation you are buying. Higher effort means more reasoning before the answer comes back — which costs more latency and unit cost. Choose per call: a FAQ lookup and a contract clause analysis should not spend the same budget.
autodelegates the choice. Witheffort: auto(the default), the
service reads the prompt and picks a spend level for you. Pin an explicit effort when your use case has its own latency or cost envelope.
- Budget caps are advisory.
max_latency_msandmax_estimated_cost
state your envelope; the service logs them and honors them on a best-effort basis. Set them to communicate intent — do not rely on them as hard enforcement yet.
- Steering is per call.
systemanddevelopermessages shape how the
answer is written (format, role, constraints). Multiple user messages are concatenated into one prompt.
deliberationis telemetry, not input. The response carries a block
recording what the request cost — effort honored, latency, estimated unit cost, plus internal quality signals. Read the cost fields; treat the rest as opaque telemetry and never feed it back as input.
- Text only, for now. One message is capped at 32,768 characters, and
streaming is not yet supported — omit stream.
The one call
A steered question with an explicit effort budget and your cost envelope:
curl -sf --max-time 280 -X POST "${CHLOE_URL}/v3/chloe/chat/completions" \
-H "Authorization: Bearer ${TOKEN}" \
-H "x-api-key: ${INAYA_API_KEY}" \
-H "x-client-app-key: ${INAYA_APP_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "chloe",
"effort": "fast",
"max_latency_ms": 8000,
"max_estimated_cost": 0.02,
"messages": [
{ "role": "system", "content": "You are a concise analyst." },
{ "role": "user", "content": "In one sentence: why do small teams ship faster?" }
]
}' | python3 -c '
import json, sys
d = json.load(sys.stdin)
print("answer:", d["choices"][0]["message"]["content"])
tel = d["deliberation"]
print("effort honored:", tel["effort"],
"| latency_ms:", tel["latency_ms"],
"| est. cost:", tel["estimated_cost"])'Expected response — 200 with an OpenAI-shaped body plus the telemetry extension (internal telemetry fields elided here — read the cost fields, treat the rest as opaque):
{
"id": "chatcmpl-…",
"object": "chat.completion",
"created": 1790257916,
"model": "chloe",
"choices": [
{ "index": 0,
"message": { "role": "assistant", "content": "Small teams ship faster because …" },
"finish_reason": "stop" }
],
"usage": { "prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0 },
"deliberation": { "effort": "fast", "latency_ms": 48903, "estimated_cost": 2.0 }
}Three fields to read correctly: the answer is choices[0].message.content; model simply echoes your request value (chloe when omitted); and usage is a placeholder (all zeros) reserved for a future metering release — the cost signal today is deliberation's latency_ms and estimated_cost.
NOTE
Latency scales with effort. On the local stack the fast path answers in under a minute on a small local model; deeper effort levels deliberate longer, and on fleets with mature cloud models the same calls answer faster and at finer cost granularity.
The effort knob
| Effort | What you are buying |
|---|---|
fast | Single pass — minimum latency and cost. No escalation. |
balanced | Deeper check before the answer ships; early exit when the answer is already solid. |
deep | Deliberate single-domain precision. |
maximum | The deepest deliberation the fleet can assemble for one call. |
auto | The service picks a spend level from the prompt (the default). |
Start at auto, watch deliberation.latency_ms and deliberation.estimated_cost in production traffic, and pin an explicit effort where your envelope demands it.
Error contract
Every validation failure is a 400 with a plain-text explanation, and a missing or invalid JWT is a 401:
KEYS=(-H "x-api-key: ${INAYA_API_KEY}" -H "x-client-app-key: ${INAYA_APP_KEY}")
echo "== missing JWT =="
curl -s -o /tmp/chloe_err1.json -w "%{http_code}\n" -X POST "${CHLOE_URL}/v3/chloe/chat/completions" \
"${KEYS[@]}" -H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"hi"}]}'
cat /tmp/chloe_err1.json; echo
echo "== stream requested =="
curl -s -w "\n%{http_code}\n" -X POST "${CHLOE_URL}/v3/chloe/chat/completions" \
-H "Authorization: Bearer ${TOKEN}" "${KEYS[@]}" -H "Content-Type: application/json" \
-d '{"stream":true,"messages":[{"role":"user","content":"hi"}]}'
echo "== unsupported role =="
curl -s -w "\n%{http_code}\n" -X POST "${CHLOE_URL}/v3/chloe/chat/completions" \
-H "Authorization: Bearer ${TOKEN}" "${KEYS[@]}" -H "Content-Type: application/json" \
-d '{"messages":[{"role":"assistant","content":"hi"}]}'
echo "== empty messages =="
curl -s -w "\n%{http_code}\n" -X POST "${CHLOE_URL}/v3/chloe/chat/completions" \
-H "Authorization: Bearer ${TOKEN}" "${KEYS[@]}" -H "Content-Type: application/json" \
-d '{"messages":[]}'
echo "== empty content =="
curl -s -w "\n%{http_code}\n" -X POST "${CHLOE_URL}/v3/chloe/chat/completions" \
-H "Authorization: Bearer ${TOKEN}" "${KEYS[@]}" -H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":" "}]}'
echo "== system-only messages =="
curl -s -w "\n%{http_code}\n" -X POST "${CHLOE_URL}/v3/chloe/chat/completions" \
-H "Authorization: Bearer ${TOKEN}" "${KEYS[@]}" -H "Content-Type: application/json" \
-d '{"messages":[{"role":"system","content":"You are helpful."}]}'
echo "== over the 32768-character cap =="
python3 -c 'import json; print(json.dumps({"messages":[{"role":"user","content":"x"*33000}]}))' \
| curl -s -w "\n%{http_code}\n" -X POST "${CHLOE_URL}/v3/chloe/chat/completions" \
-H "Authorization: Bearer ${TOKEN}" "${KEYS[@]}" -H "Content-Type: application/json" -d @-Expected — 401 with {"error":"Missing Authorization token"} for a missing/invalid JWT; 400 with, respectively, streaming is not yet supported; omit 'stream' or set it to false, Unsupported role 'assistant'. Only 'user', 'system', and 'developer' are supported., messages array must not be empty, message content must not be empty, at least one 'user' message is required, and message content exceeds the 32768 character limit. When the model fleet is unreachable, the call fails with 503 — treat it as retryable.
Full working example
One script (chloe_chat.sh) — QA-login, then a budgeted call whose answer and telemetry are asserted (AUTH_URL is the Auth Service — http://127.0.0.1:40004; CHLOE_URL is Chloe — http://127.0.0.1:40000; TENANT_ID is your sandbox tenant):
#!/usr/bin/env bash
set -euo pipefail
# 0. Obtain a user JWT (QA shortcut — see G-01 for production flows)
TOKEN=$(curl -sf -X POST "${AUTH_URL}/v3/auth/qa/login" \
-H "Content-Type: application/json" \
-H "x-api-key: ${INAYA_API_KEY}" \
-H "x-client-app-key: ${INAYA_APP_KEY}" \
-d "{\"device_id\": \"g21-demo-device\", \"locale\": \"en-US\", \"tenant_id\": \"${TENANT_ID}\", \"username\": \"g21-demo\"}" \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["token"])')
AUTH=(-H "Authorization: Bearer ${TOKEN}"
-H "x-api-key: ${INAYA_API_KEY}"
-H "x-client-app-key: ${INAYA_APP_KEY}")
# 1. Budgeted reasoning call — assert shape, effort honored, and telemetry
curl -sf --max-time 280 -X POST "${CHLOE_URL}/v3/chloe/chat/completions" "${AUTH[@]}" \
-H "Content-Type: application/json" \
-d '{
"model": "chloe",
"effort": "fast",
"max_latency_ms": 8000,
"max_estimated_cost": 0.02,
"messages": [
{ "role": "user", "content": "In one sentence: why do small teams ship faster?" }
]
}' | python3 -c '
import json, sys
d = json.load(sys.stdin)
assert d["object"] == "chat.completion", d
assert d["choices"][0]["finish_reason"] == "stop", d
assert d["choices"][0]["message"]["content"].strip(), "empty answer"
tel = d["deliberation"]
assert tel["effort"] == "fast", tel
assert tel["latency_ms"] > 0 and tel["estimated_cost"] > 0, tel
print("chloe call: ok")
print("answer:", d["choices"][0]["message"]["content"][:80])
print("telemetry: effort=%s latency_ms=%s est_cost=%s"
% (tel["effort"], tel["latency_ms"], tel["estimated_cost"]))'Try it live
Open the Playground → Our AI Models: Chloe is a fully functional chat UI on this exact endpoint — effort knob included, internals kept server-side.
Copy agent prompt
You are helping a developer call the Chloe reasoning endpoint (${CHLOE_URL}).
Chloe is a stateless, OpenAI-compatible reasoning surface: POST
/v3/chloe/chat/completions with header Authorization: Bearer ${TOKEN} plus the
x-api-key / x-client-app-key pair. Body: optional model label ("chloe"),
messages array (roles user, system, developer; at least one user message;
content non-empty, max 32768 chars each), optional effort budget knob
(fast|balanced|deep|maximum|auto, default auto), optional advisory
max_latency_ms / max_estimated_cost caps. No streaming — omit stream. Steps:
(1) POST one user question with effort "fast" and report
choices[0].message.content plus deliberation.effort, deliberation.latency_ms,
and deliberation.estimated_cost. (2) Explain to the developer how to choose
an effort level for latency-sensitive vs. quality-sensitive calls. Treat the
deliberation block as telemetry, never as input. Errors: 401
{"error":"Missing Authorization token"}; 400 for unsupported roles, empty
messages/content, or missing user message; 503 when the model fleet is
unreachable. Never log the JWT.API reference
- Chloe — Swagger UI · Scalar — the reasoning endpoint
Next journeys
- Choosing Evergreen vs Bella vs Chloe (G-13) — where this surface fits among the platform's three AI surfaces.
- Chatting with Bella (G-20) — the persona surface: a pre-tuned assistant instead of a budget knob.
- Your first AI chat session (G-10) — full server-side conversation memory via Evergreen sessions, when one-shot is not enough.