# Architecture Decisions

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

## ADR-001: NDJSON over SSE for Streaming

**Status:** Accepted

**Context:** Conversation creation and interaction endpoints stream multiple events back to the client. We needed to choose between Server-Sent Events (SSE), WebSocket, and Newline-Delimited JSON (NDJSON) for the HTTP streaming protocol.

**Decision:** Use NDJSON (newline-delimited JSON) for all streaming HTTP endpoints.

**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 our 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 (shared signing key)        | 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, org, 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, enabling horizontal scaling.
* **Standard claims**: `sub` (user ID), `org` (organization), `exp` (expiration) are standard JWT fields that any JWT library can validate.
* **Proactive refresh**: The 5-minute refresh window in both SDKs ensures uninterrupted operation 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, increasing request overhead slightly
* SDKs must implement token refresh logic (both do, with race condition protection via locks/shared promises)
* 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 + 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 - 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, Decision, 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](https://docs.amigo.ai/developer-guide/operations/reference/terminology-mapping))

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