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.
- package/knowledge/2.0/apps/talos/INDEX.md +10 -0
- package/knowledge/2.0/apps/talos/architecture.md +169 -0
- package/knowledge/2.0/apps/talos/features/aegra-api.md +206 -0
- package/knowledge/2.0/apps/talos/features/deployment.md +115 -0
- package/knowledge/2.0/apps/talos/features/mcp-servers.md +142 -0
- package/knowledge/2.0/apps/talos/features/observability.md +132 -0
- package/knowledge/2.0/apps/talos/features/react-agent.md +205 -0
- package/knowledge/INDEX.md +1 -0
- package/knowledge/registry.json +2 -1
- package/package.json +1 -1
|
@@ -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)
|
package/knowledge/INDEX.md
CHANGED
|
@@ -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
|
|
package/knowledge/registry.json
CHANGED
|
@@ -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