> For the complete documentation index, see [llms.txt](https://docs.amigo.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.amigo.ai/developer-guide/operations/reference/architecture-decisions.md).

# Architecture Decisions

Key architectural decisions in the Amigo AI API design and their rationale.

## ADR-001: NDJSON for Classic API Streaming

**Status:** Accepted

**Context:** Conversation creation and interaction endpoints stream multiple events back to the client. The HTTP streaming protocol had to be chosen from Server-Sent Events (SSE), WebSocket, and Newline-Delimited JSON (NDJSON).

**Decision:** Use NDJSON (newline-delimited JSON) for Classic API conversation streaming endpoints (create conversation and interact). The Platform API made a different choice: its conversation turns endpoints stream Server-Sent Events (SSE, `text/event-stream`) - see the note below.

{% hint style="info" %}
**Platform API uses SSE for turns.** The Platform API conversation turns endpoints stream SSE, not NDJSON. `POST /turns` returns an SSE stream when the request sends `Accept: text/event-stream` (and the synchronous JSON response otherwise), while `POST /turns/stream` always returns `text/event-stream`. Each frame is a typed `TurnStreamEvent`. New Platform API integrations should prefer `POST /turns/stream`.
{% endhint %}

**Rationale:**

| Factor                  | NDJSON                               | SSE                                                  | WebSocket                     |
| ----------------------- | ------------------------------------ | ---------------------------------------------------- | ----------------------------- |
| **Parsing complexity**  | Parse each line as JSON              | Event ID management, retry logic, type field parsing | Full duplex protocol, framing |
| **Client support**      | Works with any HTTP client           | Requires EventSource API or polyfill                 | Requires WebSocket API        |
| **Content types**       | Standard `application/x-ndjson`      | `text/event-stream`                                  | Binary frames                 |
| **Proxy compatibility** | Passes through standard HTTP proxies | Some proxies buffer SSE streams                      | Requires upgrade              |
| **Error handling**      | Standard HTTP status codes           | Limited to stream reconnection                       | Close codes                   |
| **Binary data**         | Base64 in JSON fields                | Text only                                            | Native binary support         |

Key advantages for this use case:

* **Simplicity.** Each line is a self-contained JSON object. No event ID tracking or reconnection logic needed.
* **Language agnostic.** Works with any language that can read lines from an HTTP response body.
* **Discriminated unions.** Each event has a `type` field that maps directly to a typed discriminated union in both SDKs.
* **Progressive parsing.** Clients can process events as they arrive without buffering the entire response.

**Consequences:**

* Clients must handle newline-delimited parsing (both SDKs provide this via async generators).
* No built-in reconnection semantics (clients implement retry via the SDK retry middleware).
* WebSocket is used separately for the real-time voice endpoint where bidirectional streaming is required.

***

## ADR-002: JWT over Session Tokens

**Status:** Accepted

**Context:** The API needs an authentication mechanism that works across multiple services, supports token refresh, and can be verified without database lookups.

**Decision:** Use JWT (JSON Web Token) bearer tokens obtained via API key exchange.

**Authentication flow:**

1. Client exchanges API key + API key ID for a JWT via `POST /user/signin_with_api_key`.
2. JWT is sent as `Authorization: Bearer {token}` on subsequent requests.
3. SDKs proactively refresh tokens 5 minutes before expiry.

**Rationale:**

| Factor                     | JWT                          | Session Tokens        | API Key Direct     |
| -------------------------- | ---------------------------- | --------------------- | ------------------ |
| **Stateless verification** | Yes (signature check)        | No (DB lookup)        | No (DB lookup)     |
| **Cross-service**          | Yes (signature verification) | No (service-specific) | Yes                |
| **Expiration**             | Built-in `exp` claim         | Manual tracking       | Never expires      |
| **Revocation**             | Requires token blacklist     | Delete from DB        | Requires rotation  |
| **Payload**                | Standard claims (sub, exp)   | Opaque identifier     | Opaque identifier  |
| **Token size**             | Larger (\~1KB)               | Small (\~32 bytes)    | Small (\~64 bytes) |

Key advantages:

* **Stateless.** API servers verify tokens without hitting a session store, which enables horizontal scaling.
* **Standard claims.** `sub` (user ID) and `exp` (expiration) are standard JWT fields that any JWT library can validate.
* **Proactive refresh.** The 5-minute refresh window in both SDKs keeps operation uninterrupted without 401 retry overhead.
* **Separation of concerns.** Long-lived API keys never travel over the wire after initial exchange. Short-lived JWTs limit exposure if intercepted.

**Consequences:**

* Tokens are larger than session IDs, which increases request overhead slightly.
* SDKs must implement token refresh logic (both SDKs implement safe concurrent token refresh).
* Token revocation requires additional infrastructure (not currently needed for API key-based auth).

***

## ADR-003: service\_hierarchical\_state\_machine Naming

**Status:** Accepted

**Context:** The platform documentation refers to "Context Graphs," the state-based architecture that structures agent reasoning and conversation flow. The API needs a field name for this entity.

**Decision:** Use `service_hierarchical_state_machine` as the API resource name.

**Rationale:**

The name was chosen to be technically precise about what the entity represents:

* **`service`.** Scoped to a service (the deployment unit that combines agent, state machine, and tools).
* **`hierarchical`.** States can be nested hierarchically (parent states containing child states).
* **`state_machine`.** The fundamental computational model: a finite set of states with defined transitions.

Why not `context_graph`?

| Concern                     | Decision                                                                                                                                                                |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Disambiguation**          | "Graph" is overloaded and could be confused with knowledge graphs, graph databases, or dependency graphs. "State machine" is unambiguous in computer science.           |
| **Implementation fidelity** | The implementation IS a hierarchical state machine. Exit conditions define transitions. States have types (Action, Annotation, Decision, Recall, Reflection, ToolCall). |
| **API stability**           | Technical names are less likely to change than marketing names. The platform docs can rename "Context Graph" without breaking the API.                                  |
| **Self-documenting**        | A developer seeing `service_hierarchical_state_machine` in a payload immediately understands the data structure without needing to read documentation.                  |

**Consequences:**

* Verbose field name increases payload sizes slightly.
* Developers must learn the mapping between platform terminology ("Context Graph") and API names.
* The terminology mapping page bridges this gap. See [Terminology Mapping](/developer-guide/operations/reference/terminology-mapping.md).

**See also:** [Terminology Mapping](/developer-guide/operations/reference/terminology-mapping.md) for the complete mapping between platform concepts and API names.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.amigo.ai/developer-guide/operations/reference/architecture-decisions.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
