#region AgentChat.DataModel [C:3] [TYPE ADR] [SEMANTICS data-model,agent-chat,final]
@BRIEF Final data model — structured JSON metadata, PostgreSQL checkpointer, dual-identity RBAC, no custom WebSocket types.

## 1. Streaming Metadata Protocol

Each `event.data` is a `ChatMessage` with optional structured `metadata`:

```typescript
interface StreamMetadata {
  type?: "stream_token" | "tool_start" | "tool_end" | "tool_error" 
       | "confirm_required" | "confirm_resolved" | "error";
  token?: string;
  tool?: string;
  input?: Record<string, unknown>;
  output?: Record<string, unknown>;
  error?: string;
  prompt?: string;
  thread_id?: string;
  result?: "confirmed" | "denied";
  code?: string;
  detail?: string;
}
```

No `agent-ws.ts`. No custom WebSocket types. No emoji prefix parsing.

## 2. SQLAlchemy

Tables: `agent_conversations`, `agent_messages`. Legacy `assistant_messages` preserved.

## 3. Pydantic Schemas

`ConversationItem`, `ConversationListResponse`, `MessageItem`, `HistoryResponse`, `DeleteResponse`.

## 4. TypeScript DTOs

`frontend/src/types/agent.ts` — matches Pydantic schemas. Includes `StreamMetadata`.

## 5. PostgreSQL Checkpointer

LangGraph checkpointer: `langgraph-checkpoint-postgres`. Thread ID = conversation_id. Survives container restarts. Same PostgreSQL instance as FastAPI.

## 6. Dual Identity RBAC

```
Authorization: Bearer {service_jwt}
X-User-JWT: {user_jwt}
```

Audit: `{service_actor: "agent", user_actor: user_id}`.

#endregion AgentChat.DataModel
