Files
ss-tools/specs/033-gradio-agent-chat/data-model.md
2026-07-03 16:47:10 +03:00

2.8 KiB

#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:

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.

4a. Frontend Screen-State Derivations

AgentChatModel owns operator-only derived state. These fields are not persisted and do not cross the API boundary:

type AgentProcessStepState = "done" | "active" | "blocked" | "idle";

interface AgentProcessStep {
  id: "context" | "reasoning" | "tools" | "confirmation" | "result";
  label: string;
  state: AgentProcessStepState;
}

Derived state:

  • hasSilentStream: streaming with no token, no tool call, no confirmation/checkpoint.
  • userFacingStatusTitle / userFacingStatusDetail: operator-readable status copy.
  • processSteps: UI process strip; currently inferred from stream/tool/confirmation/error state.
  • cleanVisibleMessageText(rawText): strips hidden runtime/prefetch/upload context before rendering or retrying.

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}.

7. Hidden Runtime Context

The backend may prepend hidden runtime context to the LLM-facing message. This is not a persisted message field.

[RUNTIME CONTEXT]
Current datetime: <ISO>
Environment: <env_id>
Rules: interpret now/start/duration from current datetime...
Dashboards: compact bounded prefetch...
[/RUNTIME CONTEXT]

<visible user text>

Persistence invariant: agent_messages.text, title generation input, and frontend-rendered user bubbles use the visible user text only.

#endregion AgentChat.DataModel