Skip to content

What is on file about a subject

GET
/api/agents/brief/
curl --request GET \
--url 'http://localhost:8000/api/agents/brief/?subject_kind=client' \
--header 'Authorization: Bearer <token>'

Measurements, live plans and prior-conversation counts for one athlete or the squad. Assembled from the same rows the agent’s own prompt reads, so the card and the agent cannot disagree about what exists — it answers “have they got something?” without asking.

agent
string

Persona key from GET /api/agents/. Accepted and ignored here — a conversation is not keyed by persona, so this cannot narrow the result.

lang
string

Reply language (en / ru / es). Defaults to en.

subject_id
string

Client id — required when subject_kind=client, ignored for team (a team subject always resolves to the caller’s active team).

subject_kind
required
string
Allowed values: client team

team or client.

Media typeapplication/json

GET /api/agents/brief/ — what is on file about a subject.

STRUCTURED, built from the domain rows. The first version reused the prompt’s prose lines and printed a Python repr of the injury JSON at a coach; prompt text is engineered for a model and is not UI copy, so the two have separate shapes over the same underlying data (agents.memory).

object
kind
required
string
label
required
string
readiness
required
integer
nullable
activity
required
string
sessions
required
integer
activities
required
Array<object>

One row of the athlete’s activity mix.

key is the raw activity so a caller can filter on it; label is what a coach reads. Both, because the chat’s activity chips need to SHOW one and ASK about the other.

object
key
required
string
label
required
string
count
required
integer
last_session_at
required
string format: date-time
nullable
metrics
required
Array<object>

One measurement, already formatted. The card does no arithmetic and no unit conversion — the values go through the same formatters the prompt uses, so the card and the agent cannot quote a number differently.

object
label
required
string
value
required
string
target
required
string
in_zone
required
boolean
nullable
injuries
required
Array<object>

Label and severity ONLY.

The stored row also carries an id, a date and the coach’s free-text note. Rendering those is what turned the first version of this card into a wall of JSON with UUIDs in it; the full note belongs on the client profile, where a coach can edit it.

object
label
required
string
severity
required
string
roster
required
object
total
required
integer
active
required
integer
at_risk
required
integer
average_score
required
number format: double
nullable
plans
required
Array<object>

One plan as the brief lists it — enough to say “they have something”, not the whole plan (the panel renders that).

agent + thread are the link back to the conversation that produced it, which is what the athlete profile’s Plans section needs (#1731). thread is null on pre-migration rows.

object
id
required
string
title
required
string
agent
required
string
thread
required
string
nullable
generated_at
required
string format: date-time
steps_total
required
integer
steps_open
required
integer
plans_total
required
integer
conversations
required
integer
last_conversation_at
required
string format: date-time
nullable
Examplegenerated
{
"kind": "example",
"label": "example",
"readiness": 1,
"activity": "example",
"sessions": 1,
"activities": [
{
"key": "example",
"label": "example",
"count": 1,
"last_session_at": "2026-04-15T12:00:00Z"
}
],
"metrics": [
{
"label": "example",
"value": "example",
"target": "example",
"in_zone": true
}
],
"injuries": [
{
"label": "example",
"severity": "example"
}
],
"roster": {
"total": 1,
"active": 1,
"at_risk": 1,
"average_score": 1
},
"plans": [
{
"id": "example",
"title": "example",
"agent": "example",
"thread": "example",
"generated_at": "2026-04-15T12:00:00Z",
"steps_total": 1,
"steps_open": 1
}
],
"plans_total": 1,
"conversations": 1,
"last_conversation_at": "2026-04-15T12:00:00Z"
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string
Examplegenerated
{
"detail": "example"
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string
Examplegenerated
{
"detail": "example"
}

The caller’s tier does not include the coaching agents.

Media typeapplication/json
object
detail
required

One of five canonical strings. The front-end paywall switches copy + CTA on this value (exact string equality — do not localise). quota_exhausted / seat_limit_reached / client_limit_reached / feature_not_in_plan lead to an upgrade CTA; subscription_suspended leads to a Billing Portal CTA so the buyer can update their payment method.

  • quota_exhausted - Session quota for the period reached 0
  • subscription_suspended - Stripe dunning in flight (past_due / unpaid)
  • seat_limit_reached - Adding another team member would exceed plan.max_seats
  • client_limit_reached - Adding another Client would exceed plan.max_client_profiles
  • feature_not_in_plan - The tier does not include this whole feature surface
string
Allowed values: quota_exhausted subscription_suspended seat_limit_reached client_limit_reached feature_not_in_plan
reset_at
required

ISO-8601 UTC timestamp the team’s current period ends. Null when the team has no live subscription (legacy un-migrated row). On Free + paid this is the renewal moment; quota refreshes to exactly plan.session_quota (NOT additive — leftover sessions don’t roll over).

string format: date-time
nullable
current_plan
required

The active plan’s role string (free, starter, professional, organization, strategic). Same value as current_role — kept as two separate fields for forward-compatibility with a future named-plan split where current_plan could carry an SKU and current_role the tier label.

string
current_role
required

The active plan’s role string. See current_plan.

string
feature

Which feature surface is locked. Present ONLY on feature_not_in_plan, so one modal can name what’s gated without a detail string per feature (#773). The only value today is agents (aikynetix/agents/services.py::AGENTS_FEATURE).

string
Examples
Example402—AgentsNotInPlan

Free team opens an agent conversation

{
"detail": "feature_not_in_plan",
"reset_at": null,
"current_plan": "free",
"current_role": "free",
"feature": "agents"
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string
Examplegenerated
{
"detail": "example"
}
Media typeapplication/json
object
detail
required

Human-readable message, or a stable machine code for the cases a client branches on. The standard envelope for 400 (validation — a field-keyed object may appear instead), 401 (missing / invalid credentials), 403 (authenticated but not permitted), and 404 (absent — cross-team records are collapsed to 404 so the API never leaks the existence of another team’s data).

string
Examplegenerated
{
"detail": "example"
}