toga-ai 1.0.89 → 1.0.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,10 @@
1
+ # talos (TOGa IQ) — 2.0 knowledge
2
+
3
+ | Doc | Summary | Files |
4
+ |-----|---------|-------|
5
+ | [TOGa IQ (talos) Architecture](architecture.md) | **TOGa IQ** is TOGA Technology's AI agent platform. | talos/libs/aegra-api/src/aegra_api/main.py, talos/libs/aegra-api/src/aegra_api/settings.py, talos/libs/aegra-api/src/aegra_api/config.py, talos/libs/aegra-api/src/aegra_api/core/tenant_router.py, talos/libs/aegra-api/src/aegra_api/core/control_plane_db.py, talos/libs/aegra-api/src/aegra_api/core/auth_middleware.py, talos/libs/aegra-api/src/aegra_api/services/run_executor.py, talos/libs/aegra-api/src/aegra_api/services/langgraph_service.py, talos/libs/aegra-api/src/aegra_api/services/graph_factory.py, talos/libs/aegra-api/src/aegra_api/services/streaming_service.py, talos/examples/react_agent/graph.py, talos/docker-compose.yml, talos/deployments/docker/Dockerfile |
6
+ | [aegra-api — Agent Protocol HTTP + Execution Pipeline](features/aegra-api.md) | `aegra-api` is the **FastAPI Agent Protocol server** at the heart of TOGa IQ. | talos/libs/aegra-api/src/aegra_api/main.py, talos/libs/aegra-api/src/aegra_api/settings.py, talos/libs/aegra-api/src/aegra_api/config.py, talos/libs/aegra-api/src/aegra_api/api/assistants.py, talos/libs/aegra-api/src/aegra_api/api/threads.py, talos/libs/aegra-api/src/aegra_api/api/runs.py, talos/libs/aegra-api/src/aegra_api/api/store.py, talos/libs/aegra-api/src/aegra_api/api/mcp.py, talos/libs/aegra-api/src/aegra_api/api/knowledge_bases.py, talos/libs/aegra-api/src/aegra_api/core/auth_middleware.py, talos/libs/aegra-api/src/aegra_api/core/auth_deps.py, talos/libs/aegra-api/src/aegra_api/core/tenant_router.py, talos/libs/aegra-api/src/aegra_api/core/control_plane_db.py, talos/libs/aegra-api/src/aegra_api/core/redis_manager.py, talos/libs/aegra-api/src/aegra_api/core/encryption.py, talos/libs/aegra-api/src/aegra_api/middleware/content_type_fix.py, talos/libs/aegra-api/src/aegra_api/middleware/rate_limiter.py, talos/libs/aegra-api/src/aegra_api/middleware/logger_middleware.py, talos/libs/aegra-api/src/aegra_api/services/broker.py, talos/libs/aegra-api/src/aegra_api/services/redis_broker.py, talos/libs/aegra-api/src/aegra_api/services/executor.py, talos/libs/aegra-api/src/aegra_api/services/local_executor.py, talos/libs/aegra-api/src/aegra_api/services/worker_executor.py, talos/libs/aegra-api/src/aegra_api/services/run_executor.py, talos/libs/aegra-api/src/aegra_api/services/langgraph_service.py, talos/libs/aegra-api/src/aegra_api/services/graph_factory.py, talos/libs/aegra-api/src/aegra_api/services/graph_streaming.py, talos/libs/aegra-api/src/aegra_api/services/streaming_service.py, talos/libs/aegra-api/src/aegra_api/services/event_store.py, talos/libs/aegra-api/alembic/env.py |
7
+ | [Deployment — Docker, Compose, Entrypoint, External PG/Redis](features/deployment.md) | TOGa IQ ships as a **single container** (`aegra` service) wrapping the `aegra-api` FastAPI server. | talos/docker-compose.yml, talos/deployments/docker/Dockerfile, talos/deployments/docker/entrypoint.sh |
8
+ | [MCP Servers — clickup-mcp and toga-db-mcp](features/mcp-servers.md) | Two internal **FastMCP** servers exposed over **HTTP** with API-key auth and PM2 process management: - **`clickup-mcp`** — ClickUp workspace surface (spaces / f | talos/mcp-servers/clickup-mcp/src, talos/mcp-servers/clickup-mcp/ecosystem.config.js, talos/mcp-servers/clickup-mcp/ecosystem.dev.config.js, talos/mcp-servers/clickup-mcp/pyproject.toml, talos/mcp-servers/clickup-mcp/.env.example, talos/mcp-servers/toga-db-mcp/src, talos/mcp-servers/toga-db-mcp/clusters.yaml, talos/mcp-servers/toga-db-mcp/ecosystem.config.js, talos/mcp-servers/toga-db-mcp/pyproject.toml, talos/mcp-servers/toga-db-mcp/.env.example |
9
+ | [Observability — Langfuse, OTEL, Prometheus, OneUptime](features/observability.md) | TOGa IQ uses **two complementary tracing planes** plus optional Prometheus metrics and external uptime monitoring: - **Langfuse (native v3 SDK)** — LLM-shaped t | talos/libs/aegra-api/src/aegra_api/observability/__init__.py, talos/libs/aegra-api/src/aegra_api/observability/setup.py, talos/libs/aegra-api/src/aegra_api/observability/base.py, talos/libs/aegra-api/src/aegra_api/observability/langfuse_provider.py, talos/libs/aegra-api/src/aegra_api/observability/langfuse_client.py, talos/libs/aegra-api/src/aegra_api/observability/otel.py, talos/libs/aegra-api/src/aegra_api/observability/metrics.py, talos/libs/aegra-api/src/aegra_api/observability/span_enrichment.py, talos/libs/aegra-api/src/aegra_api/observability/targets |
10
+ | [react_agent — LangGraph ReAct Agent with Plan, BLP, MCP, Canvas](features/react-agent.md) | `react_agent` is the **reference LangGraph agent** shipped under `examples/react_agent/`. | talos/examples/react_agent/graph.py, talos/examples/react_agent/state.py, talos/examples/react_agent/context.py, talos/examples/react_agent/prompts.py, talos/examples/react_agent/tool_router.py, talos/examples/react_agent/model_helpers.py, talos/examples/react_agent/config/context.py, talos/examples/react_agent/config/model_config.py, talos/examples/react_agent/config/tool_config.py, talos/examples/react_agent/config/plan_config.py, talos/examples/react_agent/config/memory_config.py, talos/examples/react_agent/config/mcp_config.py, talos/examples/react_agent/config/blp_config.py, talos/examples/react_agent/config/interrupt_config.py, talos/examples/react_agent/config/artifact_config.py, talos/examples/react_agent/plan/planner.py, talos/examples/react_agent/plan/nodes.py, talos/examples/react_agent/llm/system_prompt.py, talos/examples/react_agent/llm/tool_binding.py, talos/examples/react_agent/llm/message_ops.py, talos/examples/react_agent/mcp/client.py, talos/examples/react_agent/mcp/security.py, talos/examples/react_agent/mcp/session_manager.py, talos/examples/react_agent/blp/registry.py, talos/examples/react_agent/blp/embedder.py, talos/examples/react_agent/blp/nodes.py, talos/examples/react_agent/tools/__init__.py, talos/examples/react_agent/tools/code_interpreter.py, talos/examples/react_agent/tools/canvas.py, talos/examples/react_agent/tools/knowledge_base.py, talos/examples/react_agent/tools/skill_injector.py, talos/examples/react_agent/thread_name/nodes.py |
@@ -0,0 +1,169 @@
1
+ ---
2
+ title: TOGa IQ (talos) Architecture
3
+ framework: "2.0"
4
+ repo: talos
5
+ project: TOGa IQ
6
+ client: shared
7
+ type: architecture
8
+ status: active
9
+ updated: 2026-06-16
10
+ owners: [akhokhani]
11
+ files:
12
+ - talos/libs/aegra-api/src/aegra_api/main.py
13
+ - talos/libs/aegra-api/src/aegra_api/settings.py
14
+ - talos/libs/aegra-api/src/aegra_api/config.py
15
+ - talos/libs/aegra-api/src/aegra_api/core/tenant_router.py
16
+ - talos/libs/aegra-api/src/aegra_api/core/control_plane_db.py
17
+ - talos/libs/aegra-api/src/aegra_api/core/auth_middleware.py
18
+ - talos/libs/aegra-api/src/aegra_api/services/run_executor.py
19
+ - talos/libs/aegra-api/src/aegra_api/services/langgraph_service.py
20
+ - talos/libs/aegra-api/src/aegra_api/services/graph_factory.py
21
+ - talos/libs/aegra-api/src/aegra_api/services/streaming_service.py
22
+ - talos/examples/react_agent/graph.py
23
+ - talos/docker-compose.yml
24
+ - talos/deployments/docker/Dockerfile
25
+ related:
26
+ - features/aegra-api.md
27
+ - features/react-agent.md
28
+ - features/mcp-servers.md
29
+ - features/observability.md
30
+ - features/deployment.md
31
+ ---
32
+
33
+ ## Summary
34
+
35
+ **TOGa IQ** is TOGA Technology's AI agent platform. The on-disk repo is **`talos`**
36
+ (the "talos backend"). It is a Python/FastAPI implementation of the **Agent Protocol**
37
+ spec, multi-tenant, with a LangGraph **ReAct agent** as the reference agent and a
38
+ fleet of internal **MCP servers** for ClickUp and the TOGa MySQL clusters.
39
+
40
+ Unlike the PHP 2.0 apps (`_underscore`, `api2`, `worker2`), TOGa IQ has **no PHP
41
+ dependency** — it is a self-contained Python product that consumes TOGa data
42
+ read-only via the `toga-db-mcp` server. It lives under `2.0/apps/talos/` because
43
+ its consumers are 2.0-era TOGa apps (TOGa Hub, TOGa View) and TogaHub auth.
44
+
45
+ ## Top-level layout
46
+
47
+ ```
48
+ talos/
49
+ ├── libs/aegra-api/ # FastAPI server (Agent Protocol)
50
+ │ ├── src/aegra_api/
51
+ │ │ ├── api/ # ~40 route modules (assistants, threads, runs, …)
52
+ │ │ ├── core/ # auth, db, tenant routing, redis, encryption
53
+ │ │ ├── services/ # broker, executor, langgraph, streaming, event store
54
+ │ │ ├── middleware/ # logger, correlation id, rate limit, content-type
55
+ │ │ ├── models/ # Pydantic schemas (one file per API group)
56
+ │ │ ├── observability/ # Langfuse native + OTEL providers, Prometheus
57
+ │ │ └── main.py # FastAPI app factory + lifespan
58
+ │ └── alembic/ # 20 schema migrations (Jan 2025 → Mar 2026)
59
+ ├── examples/react_agent/ # Reference LangGraph agent (graph, plan, tools, blp, mcp)
60
+ ├── mcp-servers/
61
+ │ ├── clickup-mcp/ # ClickUp HTTP MCP (PM2-managed, ports 8200/8201)
62
+ │ └── toga-db-mcp/ # Multi-cluster MySQL read MCP (port 8000)
63
+ ├── deployments/docker/ # Dockerfile + entrypoint.sh
64
+ └── docker-compose.yml # Single `aegra` service (external PG + Redis)
65
+ ```
66
+
67
+ ## Five subsystems
68
+
69
+ 1. **HTTP / Agent Protocol** — `libs/aegra-api`. FastAPI app exposes ~40 routers
70
+ covering Assistants, Threads, Runs, Crons, Store, Files/Folders, Knowledge
71
+ Bases, MCP, Sandboxes, Teams, BLP, admin/tenants. Pluggable auth via
72
+ `AUTH_TYPE` ∈ {`togahub`, `entra`, `noop`}. See `features/aegra-api.md`.
73
+ 2. **Execution pipeline** — Broker → Executor → LangGraph → Streaming. Local
74
+ mode uses an in-memory queue + asyncio. Prod uses a Redis pub/sub broker +
75
+ Redis BLPOP worker queue with lease-based crash recovery. SSE replay is
76
+ backed by an in-memory ring + Postgres `run_events` table. See
77
+ `features/aegra-api.md`.
78
+ 3. **Reference agent (LangGraph)** — `examples/react_agent`. A ReAct graph with
79
+ optional planner gate, tool router, BLP semantic context selection,
80
+ running-summary memory, canvas artifacts, code-interpreter offload, and MCP
81
+ passthrough. See `features/react-agent.md`.
82
+ 4. **MCP fleet** — `clickup-mcp` and `toga-db-mcp`. Both FastMCP servers
83
+ exposed over HTTP, API-key gated, PM2-managed, with OneUptime heartbeats.
84
+ `toga-db-mcp` is the canonical read-only data plane across 4 prod clusters
85
+ + legacy + 16 non-prod environments (see `clusters.yaml`). See
86
+ `features/mcp-servers.md`.
87
+ 5. **Observability** — Langfuse (native v3 SDK) for LLM traces, OTEL (Phoenix /
88
+ Langfuse OTLP / generic OTLP / console) for spans, optional Prometheus
89
+ `/metrics`, plus OneUptime for uptime + heartbeats on MCP servers. See
90
+ `features/observability.md`.
91
+
92
+ ## Multi-tenancy
93
+
94
+ A **control plane DB** (`core/control_plane_db.py`, `control_plane_orm.py`) holds
95
+ the organization → tenant-DB mapping. `core/tenant_router.py` keeps an LRU
96
+ cache (max 100) of per-tenant `DatabaseManager` instances keyed by `org_id`.
97
+ Requests without a registered tenant return HTTP 403; tenant provisioning is
98
+ explicit (no auto-create). When `CONTROL_PLANE_DATABASE_URL` is unset the
99
+ service operates in **zero-overhead single-DB mode**.
100
+
101
+ At startup the lifespan handler migrates every registered tenant DB and seeds
102
+ base infrastructure before the health-check loop opens — slow first boot but
103
+ guarantees readiness.
104
+
105
+ ## Auth
106
+
107
+ `AUTH_TYPE` selects the backend:
108
+
109
+ - **togahub** — validates JWTs against TogaHub (`core/togahub_auth.py`).
110
+ - **entra** — Microsoft Entra ID JWT validation (`core/entra_auth.py`).
111
+ - **noop** — local-dev bypass; **never** ship to prod.
112
+
113
+ Auth is implemented as a FastAPI **dependency** (`require_auth` in
114
+ `core/auth_deps.py`), not middleware — so OpenAPI sees `401` correctly and
115
+ public routes (`/health`, `/ready`, `/live`, `/info`, `/docs`) cleanly skip it.
116
+ API-key auth (`core/api_key_auth.py`) supplements user auth for service-to-service.
117
+
118
+ ## Run lifecycle (mental model)
119
+
120
+ A client POSTs to `/threads/{id}/runs` (or stateless `/runs`). `run_preparation`
121
+ materializes the run, the **broker** publishes a `run_created` event, the
122
+ **executor** (local or worker) picks it up, `run_executor.py` calls
123
+ `langgraph_service` to compile the graph for this tenant/assistant, streams
124
+ events through `graph_streaming.py` into the broker, and the streaming endpoint
125
+ (`streaming_service.py`) replays from the broker buffer + Postgres event store
126
+ to the SSE consumer with 15s keepalive comments. Interrupts (HITL) surface as
127
+ `interrupt` events; resume re-enters via `Command(resume=…)`.
128
+
129
+ ## Storage
130
+
131
+ - **Postgres** (with `pgvector`) — primary store: assistants, threads, runs,
132
+ checkpoints, `run_events`, `store` namespace KV + embeddings, knowledge bases.
133
+ - **Redis** — broker pub/sub + replay buffer, worker BLPOP queue, sequence
134
+ counters, optional rate-limit windows.
135
+ - **S3** — file uploads (presigned URL flow via `api/files.py`).
136
+ - **Bedrock AgentCore sandbox** — code-interpreter session + large-output offload.
137
+
138
+ ## Encryption
139
+
140
+ A single global `MCP_ENCRYPTION_KEY` (Fernet) encrypts MCP server headers
141
+ before DB storage (`core/encryption.py` → `encrypt_headers` / `decrypt_headers`).
142
+ **Not per-tenant** — all tenants share one key. Document *where* a credential
143
+ lives (env var name, config key) but never the value itself.
144
+
145
+ ## Deployment
146
+
147
+ - **Container** — multi-stage `python:3.11-slim-bookworm` build with `uv`,
148
+ WeasyPrint runtime deps for HTML→PDF. Non-root `app:app`.
149
+ - **Entrypoint** — loads `.env.${ENV_NAME}` then runs
150
+ `alembic upgrade head && uvicorn aegra_api.main:app --host 0.0.0.0 --port 8000 --workers 2`.
151
+ - **Compose** — single `aegra` service; **PostgreSQL and Redis are
152
+ user-managed** (external). Health check hits `/live`. See
153
+ `features/deployment.md`.
154
+
155
+ ## Key decisions
156
+
157
+ - **Agent Protocol over a custom shape** — clients (TOGa Hub, TOGa View, third-party)
158
+ share one wire format; LangGraph Studio works out of the box.
159
+ - **Pluggable executors** — `LocalExecutor` for dev/CI, `WorkerExecutor` with
160
+ Redis lease + reaper for prod horizontal scaling.
161
+ - **Native Langfuse + OTEL side-by-side** — Langfuse for LLM-shaped traces
162
+ (token/cost), OTEL for everything else; the OTEL Langfuse target is skipped
163
+ when native mode is on to avoid duplicate spans.
164
+ - **MCP for data access** — `toga-db-mcp` is the *only* sanctioned path into
165
+ TOGa MySQL for the agent; query enforcement (read-only, LIMIT 1–1000) lives
166
+ inside the MCP, not the agent.
167
+
168
+ ## Change history
169
+ - 2026-06-16 — Initial architecture doc for talos / TOGa IQ under 2.0/apps. (akhokhani)
@@ -0,0 +1,206 @@
1
+ ---
2
+ title: aegra-api — Agent Protocol HTTP + Execution Pipeline
3
+ framework: "2.0"
4
+ repo: talos
5
+ project: TOGa IQ
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-06-16
10
+ owners: [akhokhani]
11
+ files:
12
+ - talos/libs/aegra-api/src/aegra_api/main.py
13
+ - talos/libs/aegra-api/src/aegra_api/settings.py
14
+ - talos/libs/aegra-api/src/aegra_api/config.py
15
+ - talos/libs/aegra-api/src/aegra_api/api/assistants.py
16
+ - talos/libs/aegra-api/src/aegra_api/api/threads.py
17
+ - talos/libs/aegra-api/src/aegra_api/api/runs.py
18
+ - talos/libs/aegra-api/src/aegra_api/api/store.py
19
+ - talos/libs/aegra-api/src/aegra_api/api/mcp.py
20
+ - talos/libs/aegra-api/src/aegra_api/api/knowledge_bases.py
21
+ - talos/libs/aegra-api/src/aegra_api/core/auth_middleware.py
22
+ - talos/libs/aegra-api/src/aegra_api/core/auth_deps.py
23
+ - talos/libs/aegra-api/src/aegra_api/core/tenant_router.py
24
+ - talos/libs/aegra-api/src/aegra_api/core/control_plane_db.py
25
+ - talos/libs/aegra-api/src/aegra_api/core/redis_manager.py
26
+ - talos/libs/aegra-api/src/aegra_api/core/encryption.py
27
+ - talos/libs/aegra-api/src/aegra_api/middleware/content_type_fix.py
28
+ - talos/libs/aegra-api/src/aegra_api/middleware/rate_limiter.py
29
+ - talos/libs/aegra-api/src/aegra_api/middleware/logger_middleware.py
30
+ - talos/libs/aegra-api/src/aegra_api/services/broker.py
31
+ - talos/libs/aegra-api/src/aegra_api/services/redis_broker.py
32
+ - talos/libs/aegra-api/src/aegra_api/services/executor.py
33
+ - talos/libs/aegra-api/src/aegra_api/services/local_executor.py
34
+ - talos/libs/aegra-api/src/aegra_api/services/worker_executor.py
35
+ - talos/libs/aegra-api/src/aegra_api/services/run_executor.py
36
+ - talos/libs/aegra-api/src/aegra_api/services/langgraph_service.py
37
+ - talos/libs/aegra-api/src/aegra_api/services/graph_factory.py
38
+ - talos/libs/aegra-api/src/aegra_api/services/graph_streaming.py
39
+ - talos/libs/aegra-api/src/aegra_api/services/streaming_service.py
40
+ - talos/libs/aegra-api/src/aegra_api/services/event_store.py
41
+ - talos/libs/aegra-api/alembic/env.py
42
+ related:
43
+ - ../architecture.md
44
+ - mcp-servers.md
45
+ - observability.md
46
+ ---
47
+
48
+ ## Summary
49
+
50
+ `aegra-api` is the **FastAPI Agent Protocol server** at the heart of TOGa IQ. It
51
+ exposes ~40 routers, runs LangGraph agents per-tenant, streams SSE events with
52
+ replay, and persists checkpoints + runs in Postgres (+ pgvector for the `store`
53
+ namespace).
54
+
55
+ ## Key files / entry points
56
+
57
+ | File | Purpose |
58
+ |---|---|
59
+ | `main.py` | App factory `create_app()`; lifespan: migrations → DB → control-plane → Redis → broker/executor/lease-reaper → cron scheduler → seed → health |
60
+ | `settings.py` | Env-derived config (DB URL, Redis URL, AUTH_TYPE, observability toggles) |
61
+ | `config.py` | Loads `aegra.json` / `langgraph.json` — graph factory paths, CORS, custom apps |
62
+ | `core/auth_middleware.py` + `core/auth_deps.py` | Pluggable auth backend (togahub / entra / noop) + `require_auth` FastAPI dependency |
63
+ | `core/tenant_router.py` | LRU pool (≤100) of per-tenant `DatabaseManager`s keyed by `org_id` |
64
+ | `core/control_plane_db.py` | Org/tenant registry (separate DB; `create_all` — no Alembic) |
65
+ | `services/broker.py` / `redis_broker.py` | In-memory vs Redis pub/sub broker with replay buffer |
66
+ | `services/executor.py` | Factory: `LocalExecutor` (asyncio) or `WorkerExecutor` (Redis BLPOP + lease) |
67
+ | `services/run_executor.py` | Single source of truth for run lifecycle: stream → broker → status update |
68
+ | `services/langgraph_service.py` | Compiles the graph for this tenant/assistant with checkpointer + store injected |
69
+ | `services/graph_factory.py` | Inspects 0–2-param factory signatures and invokes with coerced `ServerRuntime[T]` |
70
+ | `services/streaming_service.py` | SSE replay loop with 15s keepalive + 30-min wall-clock deadline |
71
+ | `services/event_store.py` | Postgres-backed `run_events` table (sequence-numbered) for persistent replay |
72
+
73
+ ## How it works
74
+
75
+ ### 1 — Bootstrap
76
+
77
+ `create_app()` in `main.py` (~line 579):
78
+
79
+ 1. Instantiates `FastAPI(...)` with tags for Assistants / Threads / Runs / Crons / Store / Health.
80
+ 2. Optional **custom apps** mounted from `aegra.json` config (`main.py:590`).
81
+ 3. Registers ~35 routers (`main.py:536–575`). All routers attach
82
+ `dependencies=auth_dependency` except `health` and `admin_ui`.
83
+ 4. Middleware stack (outer → inner): `ContentTypeFixMiddleware` → `CORSMiddleware`
84
+ → `CorrelationIdMiddleware` (asgi-correlation-id) → `StructLogMiddleware`.
85
+ 5. Optional `RateLimiterMiddleware` (Redis sliding window with Lua; falls back
86
+ to in-memory; exempts `/health`, `/ready`, `/live`, `/info`, `/docs`, `/redoc`).
87
+ 6. Lifespan (`main.py:146–327`): Alembic migrate → DB init → control-plane init →
88
+ Redis → broker/executor/lease-reaper → cron scheduler → base seeding →
89
+ health-check loop. Shutdown is reverse order.
90
+
91
+ ### 2 — Route surface
92
+
93
+ | Cluster | Routers |
94
+ |---|---|
95
+ | Agents/Assistants | `assistants`, `assistant_config`, `model_presets` |
96
+ | Threads & Runs | `threads`, `runs`, `stateless_runs`, `thread_forks` |
97
+ | Async | `crons` |
98
+ | Persistence | `store` (pgvector-backed namespace KV + semantic search) |
99
+ | Knowledge/Files | `knowledge_bases`, `files`, `folders` |
100
+ | MCP | `mcp`, `mcp_servers` |
101
+ | Sandbox | `sandbox_configs`, `sandbox_sessions`, `sandbox_artifacts`, `code_interpreters` |
102
+ | Admin/Ops | `admin_ui`, `tenants`, `system_config`, `tours`, `export` |
103
+ | Collaboration | `chat_shares`, `group_chat`, `group_events`, `message_feedback` |
104
+ | AI helpers | `ai_chat`, `ai_generate` |
105
+ | Integrations | `teams`, `blp`, `api_keys` |
106
+
107
+ ### 3 — Auth
108
+
109
+ `AUTH_TYPE` selects the backend: **togahub** (TogaHub JWTs via
110
+ `core/togahub_auth.py`) / **entra** (Microsoft Entra ID via `core/entra_auth.py`)
111
+ / **noop** (dev only). `require_auth` in `auth_deps.py` injects a `User` with
112
+ `org_id` (default `"default"`). Public routes skip auth: `/health`, `/ready`,
113
+ `/live`, `/info`, `/docs`, `/openapi.json`.
114
+
115
+ ### 4 — Multi-tenancy
116
+
117
+ When `CONTROL_PLANE_DATABASE_URL` is set, a `default` tenant is auto-registered,
118
+ every registered tenant DB is migrated/seeded inside the lifespan, and
119
+ `tenant_router.get_db_manager(org_id)` returns or creates the per-tenant
120
+ `DatabaseManager` (LRU eviction at 100). Missing org → HTTP 403. Single-DB mode
121
+ (no control plane) uses the global `db_manager` singleton with zero overhead.
122
+
123
+ ### 5 — Run / execution pipeline
124
+
125
+ ```
126
+ POST /threads/{id}/runs
127
+ → run_preparation creates the Run row
128
+ → broker.publish("run_created")
129
+ → executor picks up
130
+ LocalExecutor → asyncio task in-process
131
+ WorkerExecutor → Redis BLPOP, lease + heartbeat, reaper re-enqueues on crash
132
+ → run_executor.execute():
133
+ langgraph_service.compile(tenant, assistant)
134
+ graph_streaming.stream(graph, input) → broker
135
+ update run status (running → success/error/interrupted)
136
+ → streaming_service.stream(run_id) replays broker buffer + event_store
137
+ to SSE consumer (15s keepalive comments; 30-min default deadline)
138
+ ```
139
+
140
+ ### 6 — Event replay (dual storage)
141
+
142
+ - **Broker buffer** — last ~10k events per run in memory (TTL auto-evict in
143
+ Redis mode). Cheap reconnect.
144
+ - **`event_store` Postgres table** — sequence-numbered persistent log for
145
+ longer-window replay or post-hoc analysis.
146
+
147
+ ### 7 — Graph factory
148
+
149
+ `graph_factory.classify_factory()` inspects the factory's signature (0, 1, or 2
150
+ params; either order) and registers a dispatch hook. `invoke_factory()` builds
151
+ a `ServerRuntime[T]` from the per-request context and invokes the factory.
152
+ Base graphs are cached; factory graphs rebuild fresh with checkpointer/store
153
+ injected — thread-safe by construction (no locks).
154
+
155
+ ### 8 — Alembic
156
+
157
+ `alembic/env.py` reads the URL via `config.attributes` (not the configparser
158
+ section) to dodge ConfigParser's `%`-interpolation choking on password
159
+ characters. 20 migrations to date (Jan 2025 → Mar 2026): initial schema, run
160
+ status transitions, performance indexes, sandbox configs, normalized config
161
+ tables.
162
+
163
+ ### 9 — Redis usage
164
+
165
+ `core/redis_manager.py` is a singleton with connection pooling. Roles: broker
166
+ pub/sub + replay (Redis Lists, ~10-min TTL); worker BLPOP queue; sequence
167
+ counters (`INCR` for cross-instance ordering); rate-limit windows (optional).
168
+ Disable via `REDIS_BROKER_ENABLED=false` for pure local mode.
169
+
170
+ ### 10 — Notable middleware
171
+
172
+ - **`ContentTypeFixMiddleware`** — rewrites `text/plain` → `application/json`
173
+ on POST/PUT/PATCH so LangGraph Studio's quirky client works.
174
+ - **`RateLimiterMiddleware`** — Redis sliding window with Lua atomicity; falls
175
+ back to in-memory if Redis is offline.
176
+ - **`StructLogMiddleware`** — structured logs with correlation IDs (status,
177
+ method, duration, client IP).
178
+
179
+ ## Data model
180
+
181
+ Primary tables (Postgres): `assistants`, `assistant_versions`,
182
+ `assistant_configs`, `model_presets`; `threads`, `thread_forks`, `runs`,
183
+ `run_events` (sequenced), `crons`; `store` (pgvector embeddings + namespace KV);
184
+ `knowledge_bases`, `files`, `folders`; `mcp_servers` (Fernet-encrypted headers);
185
+ `sandbox_configs`, `sandbox_sessions`, `sandbox_artifacts`. Control-plane DB:
186
+ `organizations`, `tenants`.
187
+
188
+ ## Client variations
189
+
190
+ None — uniform across clients. Per-tenant data isolation is enforced by
191
+ `tenant_router`, not at the client level.
192
+
193
+ ## Gotchas / known issues
194
+
195
+ - **First boot is slow** — lifespan migrates every registered tenant DB before
196
+ opening the health-check loop. Plan for >30s startup with many tenants.
197
+ - **`MCP_ENCRYPTION_KEY` is global**, not per-tenant. Rotating it requires
198
+ decrypt-then-re-encrypt for all `mcp_servers` rows.
199
+ - **`noop` AUTH_TYPE leaks everything** — never deploy with it set.
200
+ - **LangGraph Studio sends `text/plain`** — relying on `ContentTypeFixMiddleware`.
201
+ Removing that middleware breaks Studio.
202
+ - **Alembic password chars** — keep the `config.attributes` URL passing pattern
203
+ in `env.py`; configparser interpolation will mangle `%` in passwords.
204
+
205
+ ## Change history
206
+ - 2026-06-16 — Initial aegra-api feature doc (HTTP layer + execution pipeline). (akhokhani)
@@ -0,0 +1,115 @@
1
+ ---
2
+ title: Deployment — Docker, Compose, Entrypoint, External PG/Redis
3
+ framework: "2.0"
4
+ repo: talos
5
+ project: TOGa IQ
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-06-16
10
+ owners: [akhokhani]
11
+ files:
12
+ - talos/docker-compose.yml
13
+ - talos/deployments/docker/Dockerfile
14
+ - talos/deployments/docker/entrypoint.sh
15
+ related:
16
+ - ../architecture.md
17
+ - aegra-api.md
18
+ - mcp-servers.md
19
+ - observability.md
20
+ ---
21
+
22
+ ## Summary
23
+
24
+ TOGa IQ ships as a **single container** (`aegra` service) wrapping the
25
+ `aegra-api` FastAPI server. Postgres + Redis are **user-managed externally**
26
+ (not in compose). Migrations run on every container start. MCP servers ship
27
+ separately and are PM2-managed (see `mcp-servers.md`).
28
+
29
+ ## Key files / entry points
30
+
31
+ | File | Purpose |
32
+ |---|---|
33
+ | `docker-compose.yml` | Single `aegra` service, env-file driven, resource limits, health check on `/live` |
34
+ | `deployments/docker/Dockerfile` | Multi-stage build: `python:3.11-slim-bookworm` + `uv`, lean runtime image, non-root user |
35
+ | `deployments/docker/entrypoint.sh` | Loads `.env.${ENV_NAME}` then runs `alembic upgrade head && uvicorn aegra_api.main:app ...` |
36
+
37
+ ## How it works
38
+
39
+ ### Dockerfile — multi-stage
40
+
41
+ **Builder stage:**
42
+
43
+ - Base: `python:3.11-slim-bookworm`.
44
+ - Installs `uv` (v0.9.26) + build deps (`libpq-dev`, `build-essential`).
45
+ - Freezes deps from `uv.lock` and **exports the `aegra-api` package only**
46
+ (no dev deps).
47
+ - Pre-compiles bytecode for faster cold start.
48
+
49
+ **Final stage:**
50
+
51
+ - Lightweight runtime base (no build tools).
52
+ - Installs runtime libs: `ca-certificates`, `libglib2.0`, `libpango`,
53
+ `libcairo` (for WeasyPrint HTML→PDF).
54
+ - Copies pre-built wheels + assets: `alembic.ini`, migrations, skills,
55
+ examples, BLP models.
56
+ - Copies fallback env files: `.env.prod`, `.env.beta`.
57
+ - **Entrypoint:** `/app/entrypoint.sh`.
58
+ - **Default CMD:** `alembic upgrade head && uvicorn aegra_api.main:app
59
+ --host 0.0.0.0 --port 8000 --workers 2`
60
+ - **Security:** runs as non-root `app:app`; `rwx` only on
61
+ `/app/{examples,alembic,skills,blp}`.
62
+
63
+ ### entrypoint.sh
64
+
65
+ Loads `.env.${ENV_NAME}` if present; falls back to vars already set in the
66
+ process environment. Then `exec`s the CMD. Migration on every start is
67
+ intentional — keeps containers self-healing on schema drift.
68
+
69
+ ### docker-compose.yml
70
+
71
+ Single `aegra` service:
72
+
73
+ - **Ports:** `${PORT:-8000}:${PORT:-8000}` (overrideable).
74
+ - **Env file:** `.env.prod` (default) or `${ENV_FILE}`.
75
+ - **Resources:** limits `4 CPU / 4 GiB`; reservations `1 CPU / 1 GiB`.
76
+ - **Health check:** `GET /live` every 30 s, 3 retries, 40 s start grace.
77
+ - **Restart policy:** `unless-stopped`.
78
+ - **External deps (user-managed, not in compose):**
79
+ - PostgreSQL with `pgvector` (primary DB + control-plane DB).
80
+ - Redis (broker / worker queue / rate limit).
81
+ - **Volumes:** none in compose; persistence lives on external PG/Redis.
82
+
83
+ ## Data model
84
+
85
+ No new schema introduced by deployment. `alembic upgrade head` reconciles
86
+ the existing schema; control-plane DB uses `create_all` (idempotent).
87
+
88
+ ## Client variations
89
+
90
+ `.env.${ENV_NAME}` is the per-environment seam:
91
+
92
+ - `.env.prod` — production.
93
+ - `.env.beta` — beta / staging.
94
+ - Any `.env.<name>` works — entrypoint loads by `ENV_NAME`.
95
+
96
+ Clients themselves are tenants inside one deployment, not separate compose
97
+ stacks (see `aegra-api.md` §4 multi-tenancy).
98
+
99
+ ## Gotchas / known issues
100
+
101
+ - **External PG / Redis are NOT in compose.** Set the URLs in `.env.${ENV_NAME}`
102
+ *before* `docker compose up` or migrations crash the container into a
103
+ restart loop.
104
+ - **Migrations on every start** — long migrations delay first-request
105
+ readiness. The compose `start_period: 40 s` is a generous default; raise
106
+ it if rolling out a heavy migration.
107
+ - **WeasyPrint libs are runtime, not build, deps** — removing them shrinks
108
+ the image but breaks any HTML→PDF feature (PDF tools / canvas exports).
109
+ - **`--workers 2`** is the default. Set `WORKERS=N` to override. Multi-worker
110
+ + `LocalExecutor` is fine; multi-worker + `WorkerExecutor` requires Redis.
111
+ - **Image must be non-root.** Some legacy code paths assumed root file
112
+ ownership; fix the code path, don't chown back to root.
113
+
114
+ ## Change history
115
+ - 2026-06-16 — Initial deployment feature doc. (akhokhani)
@@ -0,0 +1,142 @@
1
+ ---
2
+ title: MCP Servers — clickup-mcp and toga-db-mcp
3
+ framework: "2.0"
4
+ repo: talos
5
+ project: TOGa IQ
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-06-16
10
+ owners: [akhokhani]
11
+ files:
12
+ - talos/mcp-servers/clickup-mcp/src
13
+ - talos/mcp-servers/clickup-mcp/ecosystem.config.js
14
+ - talos/mcp-servers/clickup-mcp/ecosystem.dev.config.js
15
+ - talos/mcp-servers/clickup-mcp/pyproject.toml
16
+ - talos/mcp-servers/clickup-mcp/.env.example
17
+ - talos/mcp-servers/toga-db-mcp/src
18
+ - talos/mcp-servers/toga-db-mcp/clusters.yaml
19
+ - talos/mcp-servers/toga-db-mcp/ecosystem.config.js
20
+ - talos/mcp-servers/toga-db-mcp/pyproject.toml
21
+ - talos/mcp-servers/toga-db-mcp/.env.example
22
+ related:
23
+ - ../architecture.md
24
+ - react-agent.md
25
+ - deployment.md
26
+ ---
27
+
28
+ ## Summary
29
+
30
+ Two internal **FastMCP** servers exposed over **HTTP** with API-key auth and
31
+ PM2 process management:
32
+
33
+ - **`clickup-mcp`** — ClickUp workspace surface (spaces / folders / lists /
34
+ tasks / comments / attachments) with allowlist-scoped access.
35
+ - **`toga-db-mcp`** — Read-only multi-cluster MySQL access across TOGa's prod,
36
+ legacy, and 16 non-prod environments. The **canonical** path for the agent
37
+ to read TOGa data.
38
+
39
+ Both are consumed by the `react_agent` via the standard MCP loader and by
40
+ external clients (Claude Desktop, internal tooling) via API-key auth.
41
+
42
+ ## Key files / entry points
43
+
44
+ | Server | File | Purpose |
45
+ |---|---|---|
46
+ | clickup-mcp | `src/clickup_mcp/server.py` | FastMCP app, Starlette + APIKeyMiddleware |
47
+ | clickup-mcp | `ecosystem.config.js` | PM2 prod + dev instances (ports 8200, 8201) |
48
+ | toga-db-mcp | `src/toga_db_mcp/server.py` | FastMCP app, AuthMiddleware (X-API-Key) |
49
+ | toga-db-mcp | `clusters.yaml` | Cluster ↔ environment ↔ schema-group map (22 envs) |
50
+ | toga-db-mcp | `src/toga_db_mcp/pool.py` | aiomysql lazy per-cluster async pools |
51
+
52
+ ## How it works
53
+
54
+ ### clickup-mcp
55
+
56
+ - **Transport:** HTTP (Uvicorn). Ports **8200 prod**, **8201 dev**.
57
+ - **Auth:** `X-API-Key` validated by `APIKeyMiddleware`.
58
+ - **Tools (18):**
59
+ - `clickup_discover_hierarchy` — scans workspace tree to enumerate IDs for
60
+ allowlist config (the only unrestricted tool).
61
+ - `clickup_list_teams`
62
+ - `clickup_list_spaces`, `clickup_list_folders`, `clickup_list_lists` —
63
+ filtered by `ALLOWED_SPACE_IDS`, `ALLOWED_FOLDER_IDS`, `ALLOWED_LIST_IDS`.
64
+ - `clickup_list_tasks`, `clickup_get_task`, `clickup_create_task`,
65
+ `clickup_update_task` — guarded by list-membership check.
66
+ - `clickup_list_comments`, `clickup_create_comment`,
67
+ `clickup_upload_attachment`.
68
+ - **PM2:** 2 instances (prod, dev) with `max_memory_restart: 500M`,
69
+ `restart_delay: 5000`, `max_restarts: 10`, 30 s request timeout.
70
+ - **Observability:** OneUptime heartbeat + incident open on 2 consecutive
71
+ ClickUp API health-check failures (60 s interval).
72
+
73
+ ### toga-db-mcp
74
+
75
+ - **Transport:** HTTP (Uvicorn). Port **8000**.
76
+ - **Auth:** `X-API-Key`; optional soft User-Agent filter for claude.ai-only
77
+ dev mode.
78
+ - **Multi-cluster topology (`clusters.yaml`):**
79
+ - **Prod (4 dedicated clusters):**
80
+ - `prod-core` → platform schemas (Core, Forecast, Team) — authoritative
81
+ client lookup.
82
+ - `prod-client` → `Client_<Name>` (active per-client data).
83
+ - `prod-archive` → `Archive_<Name>` (historical snapshots, separate host).
84
+ - `prod-logs` → Logs + `Logs_<Name>` (activity / transaction logs).
85
+ - **Legacy (1 all-in-one):** `TOGA_<Name>`, `TOGaLogs_<Name>`, `Vision*`,
86
+ `TOGaDesk*` schemas.
87
+ - **Non-Prod (16 envs, all-in-one):** dev-sandbox, client-sandbox,
88
+ client-alpha/beta/gamma, qa-*, qc-*, stage, demo — V2 naming throughout.
89
+ - **Schema classification** (`clusters.yaml`): 8 groups — `platform`,
90
+ `tenants`, `archive`, `tenant_logs`, `support`, `vision`, `standalone`,
91
+ `system`. System schemas (`mysql`, `information_schema`, etc.) excluded.
92
+ - **Tools (10, all read-only):**
93
+ - `toga_health` — pool status per cluster (connected/failed, free conns).
94
+ - `toga_list_environments` — 22 envs with aliases.
95
+ - `toga_list_clusters(env)` — clusters + schema groups serving an env.
96
+ - `toga_list_schemas(env, group?)` — case-sensitive schema names.
97
+ - `toga_list_tables(env, schema_name)` — tables + row counts.
98
+ - `toga_describe_table(env, schema_name, table_name)` — column metadata.
99
+ - `toga_search_tables(env, keyword)`, `toga_search_columns(env, keyword)`
100
+ — fuzzy lookup.
101
+ - `toga_query(env, schema_name, sql, limit=100)` — read-only with **LIMIT
102
+ enforcement (1–1000)**.
103
+ - `toga_sample_data(env, schema_name, table_name, limit)` — preview rows.
104
+ - **Connection pool:** `aiomysql` async manager per cluster. Defaults
105
+ `min=1, max=5`. Lazy init on first tool call.
106
+ - **PM2:** single instance, `max_memory_restart: 500M`, log files in
107
+ `/home/ubuntu/.pm2/logs/`, auto-restart enabled.
108
+ - **Observability:** OneUptime heartbeat + per-cluster health monitoring
109
+ (60 s); incident on prod env only.
110
+
111
+ ## Data model
112
+
113
+ `toga-db-mcp` is **read-only** by contract. No schema of its own — reads flow
114
+ through the per-environment pool to MySQL clusters defined in `clusters.yaml`.
115
+ `clickup-mcp` is a stateless thin wrapper over the ClickUp v2 REST API; no DB.
116
+
117
+ ## Client variations
118
+
119
+ `toga-db-mcp`'s prod-vs-non-prod split is intentional: one MCP exposes 22
120
+ environments; the agent picks via `env` parameter on every tool call.
121
+ `clickup-mcp` is workspace-singular — different workspaces deploy separate PM2
122
+ instances (separate ports + ALLOWED_* envs).
123
+
124
+ ## Gotchas / known issues
125
+
126
+ - **Schema names are case-sensitive** in `toga-db-mcp` — must match MySQL
127
+ literal exactly. Pass a search tool result; don't hand-type.
128
+ - **`toga_query` LIMIT clamp** silently truncates at 1000. If you need more,
129
+ page via WHERE/keyset — do not bypass.
130
+ - **ClickUp allowlist must be explicit** — every list/folder/space ID enters
131
+ via env var. `clickup_discover_hierarchy` is the only way to enumerate them
132
+ on first setup; lock it down once the allowlist is populated.
133
+ - **PM2 logs path is hard-coded** (`/home/ubuntu/.pm2/logs/`). On non-ubuntu
134
+ hosts override via `PM2_HOME` before `pm2 start`.
135
+ - **API keys** are required everywhere — no anonymous mode. Lost key =
136
+ redeploy with a new key; no rotation endpoint.
137
+ - **OneUptime heartbeats** open prod incidents on 2 consecutive failures —
138
+ add the heartbeat URL to `.env` before first start or you get false-positive
139
+ pages.
140
+
141
+ ## Change history
142
+ - 2026-06-16 — Initial mcp-servers feature doc (clickup-mcp + toga-db-mcp). (akhokhani)
@@ -0,0 +1,132 @@
1
+ ---
2
+ title: Observability — Langfuse, OTEL, Prometheus, OneUptime
3
+ framework: "2.0"
4
+ repo: talos
5
+ project: TOGa IQ
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-06-16
10
+ owners: [akhokhani]
11
+ files:
12
+ - talos/libs/aegra-api/src/aegra_api/observability/__init__.py
13
+ - talos/libs/aegra-api/src/aegra_api/observability/setup.py
14
+ - talos/libs/aegra-api/src/aegra_api/observability/base.py
15
+ - talos/libs/aegra-api/src/aegra_api/observability/langfuse_provider.py
16
+ - talos/libs/aegra-api/src/aegra_api/observability/langfuse_client.py
17
+ - talos/libs/aegra-api/src/aegra_api/observability/otel.py
18
+ - talos/libs/aegra-api/src/aegra_api/observability/metrics.py
19
+ - talos/libs/aegra-api/src/aegra_api/observability/span_enrichment.py
20
+ - talos/libs/aegra-api/src/aegra_api/observability/targets
21
+ related:
22
+ - ../architecture.md
23
+ - aegra-api.md
24
+ - mcp-servers.md
25
+ ---
26
+
27
+ ## Summary
28
+
29
+ TOGa IQ uses **two complementary tracing planes** plus optional Prometheus
30
+ metrics and external uptime monitoring:
31
+
32
+ - **Langfuse (native v3 SDK)** — LLM-shaped traces with token counts, cost,
33
+ prompt linking. Best signal-to-noise for agent debugging.
34
+ - **OpenTelemetry** — application + LangChain spans for everything else,
35
+ multi-target export (Phoenix, Langfuse OTLP, generic OTLP, console).
36
+ - **Prometheus** (optional) — HTTP + Python runtime metrics on `/metrics`.
37
+ - **OneUptime** — heartbeats + incident management for the MCP fleet.
38
+
39
+ ## Key files / entry points
40
+
41
+ | File | Purpose |
42
+ |---|---|
43
+ | `observability/setup.py` | Registers OTEL + Langfuse native with the central `ObservabilityManager` and calls `setup()` |
44
+ | `observability/base.py` | `ObservabilityManager` and provider interface |
45
+ | `observability/langfuse_provider.py` | Native Langfuse v3 callback handler (enabled by `LANGFUSE_NATIVE_MODE=true`) |
46
+ | `observability/langfuse_client.py` | Singleton client wrapping the SDK |
47
+ | `observability/otel.py` | Global `TracerProvider` + `BatchSpanProcessor` + `LangChainInstrumentor` (OpenInference) |
48
+ | `observability/metrics.py` | Prometheus exporter (`ENABLE_PROMETHEUS_METRICS=true`) |
49
+ | `observability/span_enrichment.py` | Adds tenant / user / run attributes to spans |
50
+ | `observability/targets/` | Exporter target adapters (Phoenix, Langfuse OTLP, generic OTLP, console) |
51
+
52
+ ## How it works
53
+
54
+ ### 1 — Setup ordering
55
+
56
+ `setup.py` reads env and registers providers in order:
57
+
58
+ 1. `otel_provider.setup()` — global instrumentation if `OTEL_TARGETS` is set.
59
+ 2. `langfuse_provider` — native mode if `LANGFUSE_NATIVE_MODE=true` and creds
60
+ present.
61
+ 3. `metrics.install()` — Prometheus exporter mounted at `/metrics` if enabled.
62
+
63
+ Active providers are logged on startup so a misconfigured environment is
64
+ visible from the first log line.
65
+
66
+ ### 2 — Langfuse native
67
+
68
+ `langfuse_provider.py` wires a `CallbackHandler` into every LangChain/LangGraph
69
+ call. Token counts, cost, and prompt-linking come from the SDK. Enable
70
+ conditions (all three required):
71
+
72
+ - `LANGFUSE_NATIVE_MODE=true`
73
+ - `LANGFUSE_PUBLIC_KEY` + `LANGFUSE_SECRET_KEY` set
74
+ - `LANGFUSE` listed in `OTEL_TARGETS`
75
+
76
+ LangChain `config` metadata (`user_id`, `session_id`, `tags`) is picked up
77
+ automatically — attach it once and traces are filterable by it end-to-end.
78
+
79
+ ### 3 — OpenTelemetry
80
+
81
+ `otel.py` builds a global `TracerProvider` with a `BatchSpanProcessor` and
82
+ attaches `span_enrichment.enrich(span)` for tenant / user / run-id attribution.
83
+ LangChain instrumentation is via OpenInference (`LangChainInstrumentor`).
84
+
85
+ Multi-target export — set `OTEL_TARGETS` to a comma-separated list:
86
+
87
+ - **PHOENIX** — live trace visualization at the Phoenix endpoint.
88
+ - **LANGFUSE** — Langfuse OTLP. **Skipped** when native mode is on, to avoid
89
+ duplicate spans.
90
+ - **GENERIC** — any OTLP endpoint (Jaeger, Tempo, etc.).
91
+ - **CONSOLE** — debug printing if `OTEL_CONSOLE_EXPORT=true`.
92
+
93
+ ### 4 — Prometheus
94
+
95
+ Optional. Enable with `ENABLE_PROMETHEUS_METRICS=true`. Exposes `/metrics` in
96
+ Prometheus exposition format. Auto-excludes `/health`, `/ready`, `/live`,
97
+ `/metrics`, `/docs`, `/openapi.json` from HTTP histograms.
98
+
99
+ ### 5 — OneUptime
100
+
101
+ External — not in the codebase. Both MCP servers (clickup-mcp, toga-db-mcp)
102
+ post heartbeats every 60 s; two consecutive failures open an incident.
103
+ Configure via the heartbeat URL in each MCP's `.env`.
104
+
105
+ ## Data model
106
+
107
+ No persistent storage in TOGa IQ itself — traces / spans / metrics ship to
108
+ external systems (Langfuse, Phoenix, Prometheus pull, OneUptime).
109
+
110
+ ## Client variations
111
+
112
+ None. Observability is global; per-tenant filtering is applied at query time
113
+ in Langfuse / Phoenix via the `user_id` / `tenant` attributes attached by
114
+ `span_enrichment.py`.
115
+
116
+ ## Gotchas / known issues
117
+
118
+ - **Double-counted tokens** if both Langfuse native AND the OTEL-Langfuse
119
+ target are on. `otel.py` skips the Langfuse OTLP target when native mode is
120
+ on — do not undo this guard.
121
+ - **`OTEL_TARGETS` is comma-separated** — extra whitespace silently disables a
122
+ target. Use `"PHOENIX,LANGFUSE"`, not `"PHOENIX, LANGFUSE"`.
123
+ - **`/metrics` is unauthenticated** — never expose to the public internet.
124
+ Put it behind the VPC or an ALB-level auth rule.
125
+ - **OneUptime heartbeats are required for MCP prod incidents.** Missing
126
+ heartbeat URL = no monitoring; a failing MCP is invisible until users
127
+ report it.
128
+ - **Langfuse v3 SDK uses different env vars** than v2 — `LANGFUSE_HOST`,
129
+ not `LANGFUSE_BASE_URL`. Use v3 names.
130
+
131
+ ## Change history
132
+ - 2026-06-16 — Initial observability feature doc. (akhokhani)
@@ -0,0 +1,205 @@
1
+ ---
2
+ title: react_agent — LangGraph ReAct Agent with Plan, BLP, MCP, Canvas
3
+ framework: "2.0"
4
+ repo: talos
5
+ project: TOGa IQ
6
+ client: shared
7
+ type: feature
8
+ status: active
9
+ updated: 2026-06-16
10
+ owners: [akhokhani]
11
+ files:
12
+ - talos/examples/react_agent/graph.py
13
+ - talos/examples/react_agent/state.py
14
+ - talos/examples/react_agent/context.py
15
+ - talos/examples/react_agent/prompts.py
16
+ - talos/examples/react_agent/tool_router.py
17
+ - talos/examples/react_agent/model_helpers.py
18
+ - talos/examples/react_agent/config/context.py
19
+ - talos/examples/react_agent/config/model_config.py
20
+ - talos/examples/react_agent/config/tool_config.py
21
+ - talos/examples/react_agent/config/plan_config.py
22
+ - talos/examples/react_agent/config/memory_config.py
23
+ - talos/examples/react_agent/config/mcp_config.py
24
+ - talos/examples/react_agent/config/blp_config.py
25
+ - talos/examples/react_agent/config/interrupt_config.py
26
+ - talos/examples/react_agent/config/artifact_config.py
27
+ - talos/examples/react_agent/plan/planner.py
28
+ - talos/examples/react_agent/plan/nodes.py
29
+ - talos/examples/react_agent/llm/system_prompt.py
30
+ - talos/examples/react_agent/llm/tool_binding.py
31
+ - talos/examples/react_agent/llm/message_ops.py
32
+ - talos/examples/react_agent/mcp/client.py
33
+ - talos/examples/react_agent/mcp/security.py
34
+ - talos/examples/react_agent/mcp/session_manager.py
35
+ - talos/examples/react_agent/blp/registry.py
36
+ - talos/examples/react_agent/blp/embedder.py
37
+ - talos/examples/react_agent/blp/nodes.py
38
+ - talos/examples/react_agent/tools/__init__.py
39
+ - talos/examples/react_agent/tools/code_interpreter.py
40
+ - talos/examples/react_agent/tools/canvas.py
41
+ - talos/examples/react_agent/tools/knowledge_base.py
42
+ - talos/examples/react_agent/tools/skill_injector.py
43
+ - talos/examples/react_agent/thread_name/nodes.py
44
+ related:
45
+ - ../architecture.md
46
+ - aegra-api.md
47
+ - mcp-servers.md
48
+ ---
49
+
50
+ ## Summary
51
+
52
+ `react_agent` is the **reference LangGraph agent** shipped under
53
+ `examples/react_agent/`. It is a production-grade ReAct loop with an optional
54
+ **planner** gate, an LLM-driven **tool router**, **BLP** semantic context
55
+ selection, running-summary memory compaction, a versioned **canvas** artifact,
56
+ **code-interpreter** offload (Bedrock AgentCore), and transparent **MCP**
57
+ passthrough with credential resolution and session keepalive.
58
+
59
+ ## Key files / entry points
60
+
61
+ | Layer | File |
62
+ |---|---|
63
+ | Graph entry | `graph.py` (build_graph, route_model_output) |
64
+ | State schema | `state.py` |
65
+ | Per-run context | `context.py` |
66
+ | System prompt | `llm/system_prompt.py` (BLP XML injection, prompt-cache anchor) |
67
+ | Tool binding | `llm/tool_binding.py` |
68
+ | Planner | `plan/planner.py` + `plan/nodes.py` |
69
+ | Tool router | `tool_router.py` |
70
+ | BLP | `blp/registry.py`, `blp/embedder.py`, `blp/nodes.py` |
71
+ | MCP | `mcp/client.py`, `mcp/security.py`, `mcp/session_manager.py` |
72
+ | Memory | `thread_name/nodes.py`, `tools/user_memory.py`, `tools/folder_memory.py` |
73
+ | Tools | `tools/__init__.py`, `tools/providers/*` |
74
+
75
+ ## How it works
76
+
77
+ ### 1 — Graph topology
78
+
79
+ ```
80
+ __start__
81
+ → generate_thread_name (side-effect only; runs once on first human msg)
82
+ → summarize_if_needed (compress old messages → state.summary)
83
+ → select_blp_context (semantic BLP domain selection)
84
+ → create_plan (optional HITL plan gate; bypassed in tool loop)
85
+ → call_model (ReAct: bind tools, call LLM)
86
+ ├─ no tool calls → __end__
87
+ └─ tool_calls → tools (execute_tools)
88
+ → tool_loop_summarize
89
+ → call_model (loop)
90
+ ```
91
+
92
+ `route_model_output` (`graph.py:808`) routes to `tools` if the LLM emitted tool
93
+ calls **and** `remaining_steps > 1`; otherwise `__end__`. The tool loop bypasses
94
+ `create_plan` via `Command(goto=…)` — plans only fire on `__start__`.
95
+
96
+ ### 2 — State schema (`state.py`)
97
+
98
+ - `messages` — `Annotated[..., add_messages]` (merge by ID).
99
+ - `summary` — running compressed summary of older turns, re-injected as a
100
+ `SystemMessage` on each model call.
101
+ - `summary_through_count` — last index already summarized.
102
+ - `active_tool_categories` / `pending_tool_categories` — router output.
103
+ - `artifact` — versioned canvas (`type`, `title`, `language`, `contents[]`).
104
+ - `active_blp_domains` — pinned BLP domains (survives checkpoint restore).
105
+ - `plan` — status ∈ {draft, pending_approval, approved, executing, completed,
106
+ just_completed}.
107
+ - `remaining_steps` — LangGraph-managed; guarded at ≤3.
108
+
109
+ ### 3 — Configurable pieces (`config/`)
110
+
111
+ Each `*_config.py` is `from_dict`-deserializable (flat or nested JSON):
112
+
113
+ - `model_config` — model id, extended thinking, thinking budget tokens, prompt
114
+ caching, max output tokens.
115
+ - `memory_config` — max context tokens, summarization model, thresholds.
116
+ - `tool_config` — `code_interpreter_enabled`, max search results, session
117
+ timeout, nested `code_interpreter_config`.
118
+ - `plan_config` — `enabled`, `auto_approve`, planning model.
119
+ - `mcp_config` — server list with connection + credentials resolution.
120
+ - `blp_config` — directories to scan, embedding model, top-K.
121
+ - `artifact_config`, `interrupt_config` (`autonomy_level` ∈ {`full_auto`,
122
+ `interactive`}), `thread_config`.
123
+
124
+ ### 4 — Tool ecosystem
125
+
126
+ | Category | Tools |
127
+ |---|---|
128
+ | `user_memory` (always on) | `remember_user_info`, `recall_user_info`, `update_user_info` |
129
+ | `folder_memory` | save/recall/update workspace-shared context |
130
+ | `web_search` | `search_web`, `get_website` (SearxNG) |
131
+ | `knowledge_base` | `list_knowledge_bases`, `search_knowledge_base`, `retrieve_source_document` (Bedrock KB) |
132
+ | `code_interpreter` | Dynamic toolkit from Bedrock AgentCore sandbox |
133
+ | `canvas` | `create/update/rewrite/delete_artifact` |
134
+ | `visualization` | `generate_chart`, `generate_table`, `generate_metric` |
135
+ | `blp` | `query_business_logic`, `refresh_blp_context` |
136
+ | `request_input` (always on) | `interrupt()` for HITL |
137
+
138
+ Dynamic loaders: **MCP tools** via `load_mcp_tools_per_server` (keyed
139
+ `mcp:<server>`); **skills** via `skill_injector` (pre-loaded into the CI
140
+ sandbox at session start); **file injector** for workspace/file context.
141
+
142
+ **Tool router** (`tool_router.py`) — LLM-based category selection unless the
143
+ user pre-selects `selected_tool_categories`. Routes on the last human message
144
+ (cache key excludes `active_tool_categories` so the prompt cache survives the
145
+ tool loop). On router failure → bind all categories.
146
+
147
+ ### 5 — MCP integration
148
+
149
+ - **Credential resolution** (`mcp/security.py` → `MCPCredentialResolver`):
150
+ LangGraph Store → user context (`${user_id}`, `${user_email}`) → env vars.
151
+ Validates `allowed_commands`, `blocked_url_patterns`, `allowed_env_vars`,
152
+ `env_mode` against the DB-stored security config.
153
+ - **Session persistence** (`mcp/session_manager.py`): keyed by
154
+ `(server_name, user_id, connection_hash)`. TTL 45 s (below the ALB 60 s
155
+ idle timeout); liveness ping every 25 s. Lazy init; transparent reconnect.
156
+ - **Circuit breaker** (`mcp/client.py`): per-server failure counters open the
157
+ breaker for `cooldown_seconds`.
158
+
159
+ ### 6 — BLP (Business Logic Platform)
160
+
161
+ Declarative rules engine. `.blp` files hold CONSTRAINT / TERMS / CONTEXT /
162
+ ROLE / RULES blocks classified into **Tier 1** (always loaded) and **Tier 2**
163
+ (on-demand via `query_business_logic`). `blp/registry.py` scans configured
164
+ directories; `blp/embedder.py` embeds domains + blocks with **Amazon Titan
165
+ Embeddings V2** (1024 dims). `select_blp_context` picks top-K domains on the
166
+ first human message and pins them to `state.active_blp_domains`.
167
+
168
+ ### 7 — Thread naming & memory
169
+
170
+ - `generate_thread_name` runs once on the first human message via fast Bedrock
171
+ model (boto3 direct), persists the title to thread metadata, returns `{}`.
172
+ - `summarize_if_needed` compresses older messages past a threshold; summary is
173
+ injected as a `SystemMessage` before each model call.
174
+ - User & folder memory tools persist facts across threads / within a folder.
175
+
176
+ ## Data model
177
+
178
+ State persists via the LangGraph checkpointer (Postgres) injected by
179
+ `aegra-api`'s `langgraph_service`. Long-term storage: LangGraph **Store**
180
+ namespace (user/folder memory, MCP credentials per user); Bedrock
181
+ **AgentCore sandbox** (CI session state, large-output blobs; LLM sees a stub
182
+ path, not the bytes).
183
+
184
+ ## Client variations
185
+
186
+ Graph is **client-agnostic by construction**; per-tenant differences enter via
187
+ the assistant `config` row: `mcp_config.servers`, BLP directories, KB IDs.
188
+ Add a client override by configuring its assistant, not by forking the graph.
189
+
190
+ ## Gotchas / known issues
191
+
192
+ - **Tool loop must skip planner** — re-enter `call_model` via
193
+ `Command(goto="call_model")` from the tool node, else `create_plan` fires
194
+ mid-loop and the LLM re-plans every step.
195
+ - **Router cache key** must exclude `active_tool_categories` or the same user
196
+ message produces different cache keys across the loop and you lose the hit.
197
+ - **MCP session TTL < ALB idle timeout** — 45 s vs 60 s. If the ALB tightens,
198
+ drop the session TTL to match or you get spurious `ConnectionResetError`s.
199
+ - **Large-output offload threshold** ~20 KB. Raise it carefully: the LLM still
200
+ re-reads the offloaded path on retrieval (token cost).
201
+ - **`remaining_steps ≤ 3` guard** forces no-tools on the next call near the
202
+ recursion limit. Raise the limit in graph build before raising expectations.
203
+
204
+ ## Change history
205
+ - 2026-06-16 — Initial react_agent feature doc. (akhokhani)
@@ -21,6 +21,7 @@ _Auto-generated by `knowledge.js index`. Do not hand-edit._
21
21
  - **saml** (SAML SSO Gateway) — 2 doc(s) → [2.0/apps/saml/INDEX.md](2.0/apps/saml/INDEX.md)
22
22
  - **toga2-view** (TOGa View Frontend) — 0 doc(s) → [2.0/apps/toga2-view/INDEX.md](2.0/apps/toga2-view/INDEX.md)
23
23
  - **toga2-hub** (TOGa Hub) — 2 doc(s) → [2.0/apps/toga2-hub/INDEX.md](2.0/apps/toga2-hub/INDEX.md)
24
+ - **talos** (TOGa IQ) — 6 doc(s) → [2.0/apps/talos/INDEX.md](2.0/apps/talos/INDEX.md)
24
25
 
25
26
  ## standalone framework
26
27
 
@@ -13,5 +13,6 @@
13
13
  { "repo": "toga2-hub", "project": "TOGa Hub", "framework": "2.0", "role": "app", "dependsOn": ["api2"] },
14
14
  { "repo": "togatech", "project": "TOGA Technology Website", "framework": "standalone", "role": "app", "dependsOn": [] },
15
15
  { "repo": "webhook", "project": "Webhook", "framework": "1.0", "role": "app", "dependsOn": ["library"] },
16
- { "repo": "walmarttechservices", "project": "Walmart Tech Services", "framework": "1.0", "role": "app", "dependsOn": ["library"] }
16
+ { "repo": "walmarttechservices", "project": "Walmart Tech Services", "framework": "1.0", "role": "app", "dependsOn": ["library"] },
17
+ { "repo": "talos", "project": "TOGa IQ", "framework": "2.0", "role": "app", "dependsOn": [] }
17
18
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.89",
3
+ "version": "1.0.90",
4
4
  "description": "TOGA Technology Team Claude Knowledge System — shared AI coding harness with skills, knowledge base CLI, and project installer for Claude Code.",
5
5
  "keywords": [
6
6
  "claude",