fred-runtime 2.0.3__tar.gz → 2.0.7__tar.gz

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.
Files changed (107) hide show
  1. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/PKG-INFO +51 -36
  2. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/README.md +50 -35
  3. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/app/_catalogs.py +31 -1
  4. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/app/agent_app.py +159 -36
  5. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/app/config.py +9 -0
  6. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/cli/completion.py +19 -0
  7. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/cli/history_display.py +3 -0
  8. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/cli/pod_client.py +18 -0
  9. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/cli/repl.py +97 -1
  10. fred_runtime-2.0.7/fred_runtime/cli/repl_helpers.py +401 -0
  11. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/context_aware_tool.py +35 -2
  12. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/kf_workspace_client.py +18 -6
  13. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/deep/deep_runtime.py +2 -5
  14. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/graph/graph_runtime.py +147 -19
  15. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/integrations/v2_runtime/adapters.py +73 -47
  16. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/react_message_codec.py +3 -4
  17. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/react_model_adapter.py +2 -3
  18. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/react_prompting.py +32 -37
  19. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/react_runtime.py +67 -11
  20. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/react_tool_binding.py +1 -2
  21. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/react_tool_resolution.py +2 -3
  22. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime.egg-info/PKG-INFO +51 -36
  23. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime.egg-info/SOURCES.txt +6 -0
  24. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/pyproject.toml +13 -1
  25. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_agent_app.py +188 -2
  26. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_config_loader.py +81 -3
  27. fred_runtime-2.0.7/tests/test_conversational_memory.py +362 -0
  28. fred_runtime-2.0.7/tests/test_eval_collector.py +242 -0
  29. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_eval_trace.py +1 -2
  30. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_graph_runtime_observability.py +12 -2
  31. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_mcp_config.py +33 -1
  32. fred_runtime-2.0.7/tests/test_model_routing.py +579 -0
  33. fred_runtime-2.0.7/tests/test_pod_client.py +334 -0
  34. fred_runtime-2.0.7/tests/test_repl_helpers.py +123 -0
  35. fred_runtime-2.0.7/tests/test_token_expiry.py +218 -0
  36. fred_runtime-2.0.3/fred_runtime/cli/repl_helpers.py +0 -188
  37. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/__init__.py +0 -0
  38. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/app/__init__.py +0 -0
  39. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/app/config_loader.py +0 -0
  40. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/app/container.py +0 -0
  41. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/app/context.py +0 -0
  42. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/app/dependencies.py +0 -0
  43. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/app/mcp_config.py +0 -0
  44. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/app/observability_factory.py +0 -0
  45. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/app/openai_compat_router.py +0 -0
  46. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/cli/__init__.py +0 -0
  47. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/cli/entrypoint.py +0 -0
  48. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/cli/kpi_display.py +0 -0
  49. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/cli/url_helpers.py +0 -0
  50. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/client.py +0 -0
  51. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/__init__.py +0 -0
  52. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/kf_base_client.py +0 -0
  53. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/kf_fast_text_client.py +0 -0
  54. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/kf_http_client.py +0 -0
  55. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/kf_logs_client.py +0 -0
  56. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/kf_markdown_media_client.py +0 -0
  57. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/kf_vectorsearch_client.py +0 -0
  58. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/mcp_interceptors.py +0 -0
  59. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/mcp_runtime.py +0 -0
  60. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/mcp_toolkit.py +0 -0
  61. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/mcp_utils.py +0 -0
  62. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/structures.py +0 -0
  63. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/token_expiry.py +0 -0
  64. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/common/tool_node_utils.py +0 -0
  65. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/deep/__init__.py +0 -0
  66. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/eval/__init__.py +0 -0
  67. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/eval/collector.py +0 -0
  68. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/graph/__init__.py +0 -0
  69. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/integrations/__init__.py +0 -0
  70. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/integrations/v2_runtime/__init__.py +0 -0
  71. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/model_routing/__init__.py +0 -0
  72. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/model_routing/catalog.py +0 -0
  73. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/model_routing/contracts.py +0 -0
  74. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/model_routing/provider.py +0 -0
  75. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/model_routing/resolver.py +0 -0
  76. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/__init__.py +0 -0
  77. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/react_langchain_adapter.py +0 -0
  78. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/react_stream_adapter.py +2 -2
  79. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/react_tool_loop.py +5 -5
  80. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/react_tool_rendering.py +0 -0
  81. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/react_tool_utils.py +0 -0
  82. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/react/react_tracing.py +0 -0
  83. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/runtime_context.py +0 -0
  84. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/runtime_support/__init__.py +0 -0
  85. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/runtime_support/checkpoints.py +0 -0
  86. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/runtime_support/model_metadata.py +0 -0
  87. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/runtime_support/request_context_helpers.py +0 -0
  88. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/runtime_support/sql_checkpointer.py +0 -0
  89. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/runtime_support/user_token_refresher.py +0 -0
  90. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/support/__init__.py +0 -0
  91. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/support/filesystem_context.py +0 -0
  92. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/support/tool_approval.py +0 -0
  93. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime/support/tool_loop.py +0 -0
  94. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime.egg-info/dependency_links.txt +0 -0
  95. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime.egg-info/entry_points.txt +0 -0
  96. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime.egg-info/requires.txt +0 -0
  97. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/fred_runtime.egg-info/top_level.txt +0 -0
  98. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/setup.cfg +0 -0
  99. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_client.py +0 -0
  100. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_context.py +0 -0
  101. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_history.py +0 -0
  102. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_kf_workspace_client.py +0 -0
  103. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_kpi_display.py +0 -0
  104. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_openai_compat_router.py +0 -0
  105. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_smoke.py +0 -0
  106. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_url_helpers.py +0 -0
  107. {fred_runtime-2.0.3 → fred_runtime-2.0.7}/tests/test_user_token_refresher.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fred-runtime
3
- Version: 2.0.3
3
+ Version: 2.0.7
4
4
  Summary: Runtime adapters and infrastructure wiring for Fred v2 agents.
5
5
  Author-email: Thales <noreply@thalesgroup.com>
6
6
  License: Apache-2.0
@@ -58,8 +58,9 @@ fred-runtime Platform adapters + pod factory (this package)
58
58
  ```
59
59
 
60
60
  **Rule of thumb:**
61
- - Write agent logic in `fred-sdk`.
62
- - Write infrastructure adapters (DB, MCP server, Keycloak, object store) in `fred-runtime`.
61
+
62
+ - Write agent logic in `fred-sdk`.
63
+ - Write infrastructure adapters (DB, MCP server, Keycloak, object store) in `fred-runtime`.
63
64
  - `fred-sdk` must stay importable on a bare laptop with no services running.
64
65
 
65
66
  ---
@@ -79,15 +80,15 @@ app = create_agent_app(registry=REGISTRY, config=config)
79
80
 
80
81
  `create_agent_app` returns a FastAPI application that exposes:
81
82
 
82
- | Method | Path | Description |
83
- |--------|------|-------------|
84
- | `POST` | `{base_url}/agents/execute` | Single-turn execution — returns final JSON |
85
- | `POST` | `{base_url}/agents/execute/stream` | Streaming SSE execution — yields `RuntimeEvent` objects |
86
- | `GET` | `{base_url}/agents` | List registered agent IDs |
87
- | `GET` | `{base_url}/agents/sessions` | List session IDs for a user |
88
- | `GET` | `{base_url}/agents/sessions/{id}/messages` | Full conversation history for a session |
89
- | `GET` | `/v1/models` | OpenAI model list (agent IDs as model names) |
90
- | `POST` | `/v1/chat/completions` | OpenAI chat completions — works with Open WebUI, openai-python SDK, etc. |
83
+ | Method | Path | Description |
84
+ | ------ | ------------------------------------------ | ------------------------------------------------------------------------ |
85
+ | `POST` | `{base_url}/agents/execute` | Single-turn execution — returns final JSON |
86
+ | `POST` | `{base_url}/agents/execute/stream` | Streaming SSE execution — yields `RuntimeEvent` objects |
87
+ | `GET` | `{base_url}/agents` | List registered agent IDs |
88
+ | `GET` | `{base_url}/agents/sessions` | List session IDs for a user |
89
+ | `GET` | `{base_url}/agents/sessions/{id}/messages` | Full conversation history for a session |
90
+ | `GET` | `/v1/models` | OpenAI model list (agent IDs as model names) |
91
+ | `POST` | `/v1/chat/completions` | OpenAI chat completions — works with Open WebUI, openai-python SDK, etc. |
91
92
 
92
93
  The OpenAI-compatible `/v1` surface is **enabled by default**.
93
94
  Set `app.openai_compat: false` in `configuration.yaml` to disable it for internal pods.
@@ -99,11 +100,11 @@ the SQL checkpointer. The session ID is the LangGraph `thread_id`.
99
100
 
100
101
  ### `fred_runtime.runtime_support` — Infrastructure adapters
101
102
 
102
- | Module | What it provides |
103
- |--------|-----------------|
104
- | `sql_checkpointer` | Durable LangGraph checkpointer backed by SQLite (dev) or PostgreSQL (prod) |
105
- | `user_token_refresher` | Transparent Keycloak token refresh for long-lived agent sessions |
106
- | `request_context_helpers` | FastAPI dependency helpers for extracting user/session context |
103
+ | Module | What it provides |
104
+ | ------------------------- | -------------------------------------------------------------------------- |
105
+ | `sql_checkpointer` | Durable LangGraph checkpointer backed by SQLite (dev) or PostgreSQL (prod) |
106
+ | `user_token_refresher` | Transparent Keycloak token refresh for long-lived agent sessions |
107
+ | `request_context_helpers` | FastAPI dependency helpers for extracting user/session context |
107
108
 
108
109
  ---
109
110
 
@@ -119,16 +120,16 @@ Providers: OpenAI, Azure OpenAI, Mistral, Ollama, and any LangChain-compatible b
119
120
 
120
121
  HTTP clients that connect agent tools to the Fred platform services:
121
122
 
122
- | Client | Connects to |
123
- |--------|------------|
124
- | `kf_http_client` | Knowledge Flow REST API (generic) |
125
- | `kf_vectorsearch_client` | Vector search / retrieval |
126
- | `kf_markdown_media_client` | Document content (Markdown + media) |
127
- | `kf_workspace_client` | Workspace and library management |
128
- | `kf_logs_client` | Audit log retrieval |
129
- | `kf_fast_text_client` | FastText classification |
130
- | `mcp_runtime` / `mcp_toolkit` | MCP server lifecycle and tool injection |
131
- | `context_aware_tool` | Tool base class that propagates the runtime context (user, team, token) |
123
+ | Client | Connects to |
124
+ | ----------------------------- | ----------------------------------------------------------------------- |
125
+ | `kf_http_client` | Knowledge Flow REST API (generic) |
126
+ | `kf_vectorsearch_client` | Vector search / retrieval |
127
+ | `kf_markdown_media_client` | Document content (Markdown + media) |
128
+ | `kf_workspace_client` | Workspace and library management |
129
+ | `kf_logs_client` | Audit log retrieval |
130
+ | `kf_fast_text_client` | FastText classification |
131
+ | `mcp_runtime` / `mcp_toolkit` | MCP server lifecycle and tool injection |
132
+ | `context_aware_tool` | Tool base class that propagates the runtime context (user, team, token) |
132
133
 
133
134
  ---
134
135
 
@@ -176,9 +177,9 @@ or overridden with `--base-url` / `FRED_AGENT_POD_URL`.
176
177
 
177
178
  Every Fred pod uses the same two-file convention:
178
179
 
179
- | File | Purpose |
180
- |------|---------|
181
- | `.env` (path from `ENV_FILE`) | Secrets: API keys, DB URLs, Keycloak credentials |
180
+ | File | Purpose |
181
+ | ---------------------------------------------- | ------------------------------------------------------------------ |
182
+ | `.env` (path from `ENV_FILE`) | Secrets: API keys, DB URLs, Keycloak credentials |
182
183
  | `configuration.yaml` (path from `CONFIG_FILE`) | App settings: port, base URL, LLM routing, observability, security |
183
184
 
184
185
  Minimal `configuration.yaml` for a local pod:
@@ -190,6 +191,7 @@ app:
190
191
  host: "0.0.0.0"
191
192
  port: 8010
192
193
  log_level: "info"
194
+ limit_concurrency: 200
193
195
  metrics_address: "127.0.0.1"
194
196
  metrics_port: 9115
195
197
  kpi_process_metrics_interval_sec: 10
@@ -208,6 +210,10 @@ When `observability.metrics: prometheus` is enabled, `create_agent_app(...)`
208
210
  starts a dedicated Prometheus exporter on `app.metrics_address:app.metrics_port`
209
211
  and restores the shared Fred KPI pipeline, including process and SQL pool KPIs.
210
212
 
213
+ Set `app.limit_concurrency: null` to disable Uvicorn connection limiting, or a
214
+ positive integer to reject excess concurrent HTTP and WebSocket connections
215
+ with `503` before application code runs.
216
+
211
217
  ---
212
218
 
213
219
  ## Installation
@@ -229,6 +235,7 @@ Requires Python 3.12.
229
235
  A minimal pod is three files:
230
236
 
231
237
  **`main.py`**
238
+
232
239
  ```python
233
240
  from fred_runtime.app import create_agent_app, load_agent_pod_config
234
241
  from myapp.registry import REGISTRY
@@ -238,19 +245,27 @@ app = create_agent_app(registry=REGISTRY, config=config)
238
245
  ```
239
246
 
240
247
  **`__main__.py`**
248
+
241
249
  ```python
242
250
  import uvicorn
243
251
  from fred_runtime.app import load_agent_pod_config
244
252
 
245
253
  def main():
246
254
  config = load_agent_pod_config()
247
- uvicorn.run("myapp.main:app", host=config.app.host, port=config.app.port, reload=True)
255
+ uvicorn.run(
256
+ "myapp.main:app",
257
+ host=config.app.host,
258
+ port=config.app.port,
259
+ limit_concurrency=config.app.limit_concurrency,
260
+ reload=True,
261
+ )
248
262
 
249
263
  if __name__ == "__main__":
250
264
  main()
251
265
  ```
252
266
 
253
267
  **`registry.py`**
268
+
254
269
  ```python
255
270
  from fred_sdk.contracts.models import ReActAgentDefinition
256
271
 
@@ -267,11 +282,11 @@ See [fred-samples](https://github.com/ThalesGroup/fred) for a working reference
267
282
 
268
283
  ## Related packages
269
284
 
270
- | Package | PyPI | Role |
271
- |---------|------|------|
272
- | `fred-core` | [pypi](https://pypi.org/project/fred-core/) | Pure utilities — logging, model factories, embeddings, portable observability |
273
- | `fred-sdk` | [pypi](https://pypi.org/project/fred-sdk/) | Agent authoring — ReAct, Graph, tool contracts |
274
- | `fred-runtime` | [pypi](https://pypi.org/project/fred-runtime/) | This package |
285
+ | Package | PyPI | Role |
286
+ | -------------- | ---------------------------------------------- | ----------------------------------------------------------------------------- |
287
+ | `fred-core` | [pypi](https://pypi.org/project/fred-core/) | Pure utilities — logging, model factories, embeddings, portable observability |
288
+ | `fred-sdk` | [pypi](https://pypi.org/project/fred-sdk/) | Agent authoring — ReAct, Graph, tool contracts |
289
+ | `fred-runtime` | [pypi](https://pypi.org/project/fred-runtime/) | This package |
275
290
 
276
291
  ---
277
292
 
@@ -23,8 +23,9 @@ fred-runtime Platform adapters + pod factory (this package)
23
23
  ```
24
24
 
25
25
  **Rule of thumb:**
26
- - Write agent logic in `fred-sdk`.
27
- - Write infrastructure adapters (DB, MCP server, Keycloak, object store) in `fred-runtime`.
26
+
27
+ - Write agent logic in `fred-sdk`.
28
+ - Write infrastructure adapters (DB, MCP server, Keycloak, object store) in `fred-runtime`.
28
29
  - `fred-sdk` must stay importable on a bare laptop with no services running.
29
30
 
30
31
  ---
@@ -44,15 +45,15 @@ app = create_agent_app(registry=REGISTRY, config=config)
44
45
 
45
46
  `create_agent_app` returns a FastAPI application that exposes:
46
47
 
47
- | Method | Path | Description |
48
- |--------|------|-------------|
49
- | `POST` | `{base_url}/agents/execute` | Single-turn execution — returns final JSON |
50
- | `POST` | `{base_url}/agents/execute/stream` | Streaming SSE execution — yields `RuntimeEvent` objects |
51
- | `GET` | `{base_url}/agents` | List registered agent IDs |
52
- | `GET` | `{base_url}/agents/sessions` | List session IDs for a user |
53
- | `GET` | `{base_url}/agents/sessions/{id}/messages` | Full conversation history for a session |
54
- | `GET` | `/v1/models` | OpenAI model list (agent IDs as model names) |
55
- | `POST` | `/v1/chat/completions` | OpenAI chat completions — works with Open WebUI, openai-python SDK, etc. |
48
+ | Method | Path | Description |
49
+ | ------ | ------------------------------------------ | ------------------------------------------------------------------------ |
50
+ | `POST` | `{base_url}/agents/execute` | Single-turn execution — returns final JSON |
51
+ | `POST` | `{base_url}/agents/execute/stream` | Streaming SSE execution — yields `RuntimeEvent` objects |
52
+ | `GET` | `{base_url}/agents` | List registered agent IDs |
53
+ | `GET` | `{base_url}/agents/sessions` | List session IDs for a user |
54
+ | `GET` | `{base_url}/agents/sessions/{id}/messages` | Full conversation history for a session |
55
+ | `GET` | `/v1/models` | OpenAI model list (agent IDs as model names) |
56
+ | `POST` | `/v1/chat/completions` | OpenAI chat completions — works with Open WebUI, openai-python SDK, etc. |
56
57
 
57
58
  The OpenAI-compatible `/v1` surface is **enabled by default**.
58
59
  Set `app.openai_compat: false` in `configuration.yaml` to disable it for internal pods.
@@ -64,11 +65,11 @@ the SQL checkpointer. The session ID is the LangGraph `thread_id`.
64
65
 
65
66
  ### `fred_runtime.runtime_support` — Infrastructure adapters
66
67
 
67
- | Module | What it provides |
68
- |--------|-----------------|
69
- | `sql_checkpointer` | Durable LangGraph checkpointer backed by SQLite (dev) or PostgreSQL (prod) |
70
- | `user_token_refresher` | Transparent Keycloak token refresh for long-lived agent sessions |
71
- | `request_context_helpers` | FastAPI dependency helpers for extracting user/session context |
68
+ | Module | What it provides |
69
+ | ------------------------- | -------------------------------------------------------------------------- |
70
+ | `sql_checkpointer` | Durable LangGraph checkpointer backed by SQLite (dev) or PostgreSQL (prod) |
71
+ | `user_token_refresher` | Transparent Keycloak token refresh for long-lived agent sessions |
72
+ | `request_context_helpers` | FastAPI dependency helpers for extracting user/session context |
72
73
 
73
74
  ---
74
75
 
@@ -84,16 +85,16 @@ Providers: OpenAI, Azure OpenAI, Mistral, Ollama, and any LangChain-compatible b
84
85
 
85
86
  HTTP clients that connect agent tools to the Fred platform services:
86
87
 
87
- | Client | Connects to |
88
- |--------|------------|
89
- | `kf_http_client` | Knowledge Flow REST API (generic) |
90
- | `kf_vectorsearch_client` | Vector search / retrieval |
91
- | `kf_markdown_media_client` | Document content (Markdown + media) |
92
- | `kf_workspace_client` | Workspace and library management |
93
- | `kf_logs_client` | Audit log retrieval |
94
- | `kf_fast_text_client` | FastText classification |
95
- | `mcp_runtime` / `mcp_toolkit` | MCP server lifecycle and tool injection |
96
- | `context_aware_tool` | Tool base class that propagates the runtime context (user, team, token) |
88
+ | Client | Connects to |
89
+ | ----------------------------- | ----------------------------------------------------------------------- |
90
+ | `kf_http_client` | Knowledge Flow REST API (generic) |
91
+ | `kf_vectorsearch_client` | Vector search / retrieval |
92
+ | `kf_markdown_media_client` | Document content (Markdown + media) |
93
+ | `kf_workspace_client` | Workspace and library management |
94
+ | `kf_logs_client` | Audit log retrieval |
95
+ | `kf_fast_text_client` | FastText classification |
96
+ | `mcp_runtime` / `mcp_toolkit` | MCP server lifecycle and tool injection |
97
+ | `context_aware_tool` | Tool base class that propagates the runtime context (user, team, token) |
97
98
 
98
99
  ---
99
100
 
@@ -141,9 +142,9 @@ or overridden with `--base-url` / `FRED_AGENT_POD_URL`.
141
142
 
142
143
  Every Fred pod uses the same two-file convention:
143
144
 
144
- | File | Purpose |
145
- |------|---------|
146
- | `.env` (path from `ENV_FILE`) | Secrets: API keys, DB URLs, Keycloak credentials |
145
+ | File | Purpose |
146
+ | ---------------------------------------------- | ------------------------------------------------------------------ |
147
+ | `.env` (path from `ENV_FILE`) | Secrets: API keys, DB URLs, Keycloak credentials |
147
148
  | `configuration.yaml` (path from `CONFIG_FILE`) | App settings: port, base URL, LLM routing, observability, security |
148
149
 
149
150
  Minimal `configuration.yaml` for a local pod:
@@ -155,6 +156,7 @@ app:
155
156
  host: "0.0.0.0"
156
157
  port: 8010
157
158
  log_level: "info"
159
+ limit_concurrency: 200
158
160
  metrics_address: "127.0.0.1"
159
161
  metrics_port: 9115
160
162
  kpi_process_metrics_interval_sec: 10
@@ -173,6 +175,10 @@ When `observability.metrics: prometheus` is enabled, `create_agent_app(...)`
173
175
  starts a dedicated Prometheus exporter on `app.metrics_address:app.metrics_port`
174
176
  and restores the shared Fred KPI pipeline, including process and SQL pool KPIs.
175
177
 
178
+ Set `app.limit_concurrency: null` to disable Uvicorn connection limiting, or a
179
+ positive integer to reject excess concurrent HTTP and WebSocket connections
180
+ with `503` before application code runs.
181
+
176
182
  ---
177
183
 
178
184
  ## Installation
@@ -194,6 +200,7 @@ Requires Python 3.12.
194
200
  A minimal pod is three files:
195
201
 
196
202
  **`main.py`**
203
+
197
204
  ```python
198
205
  from fred_runtime.app import create_agent_app, load_agent_pod_config
199
206
  from myapp.registry import REGISTRY
@@ -203,19 +210,27 @@ app = create_agent_app(registry=REGISTRY, config=config)
203
210
  ```
204
211
 
205
212
  **`__main__.py`**
213
+
206
214
  ```python
207
215
  import uvicorn
208
216
  from fred_runtime.app import load_agent_pod_config
209
217
 
210
218
  def main():
211
219
  config = load_agent_pod_config()
212
- uvicorn.run("myapp.main:app", host=config.app.host, port=config.app.port, reload=True)
220
+ uvicorn.run(
221
+ "myapp.main:app",
222
+ host=config.app.host,
223
+ port=config.app.port,
224
+ limit_concurrency=config.app.limit_concurrency,
225
+ reload=True,
226
+ )
213
227
 
214
228
  if __name__ == "__main__":
215
229
  main()
216
230
  ```
217
231
 
218
232
  **`registry.py`**
233
+
219
234
  ```python
220
235
  from fred_sdk.contracts.models import ReActAgentDefinition
221
236
 
@@ -232,11 +247,11 @@ See [fred-samples](https://github.com/ThalesGroup/fred) for a working reference
232
247
 
233
248
  ## Related packages
234
249
 
235
- | Package | PyPI | Role |
236
- |---------|------|------|
237
- | `fred-core` | [pypi](https://pypi.org/project/fred-core/) | Pure utilities — logging, model factories, embeddings, portable observability |
238
- | `fred-sdk` | [pypi](https://pypi.org/project/fred-sdk/) | Agent authoring — ReAct, Graph, tool contracts |
239
- | `fred-runtime` | [pypi](https://pypi.org/project/fred-runtime/) | This package |
250
+ | Package | PyPI | Role |
251
+ | -------------- | ---------------------------------------------- | ----------------------------------------------------------------------------- |
252
+ | `fred-core` | [pypi](https://pypi.org/project/fred-core/) | Pure utilities — logging, model factories, embeddings, portable observability |
253
+ | `fred-sdk` | [pypi](https://pypi.org/project/fred-sdk/) | Agent authoring — ReAct, Graph, tool contracts |
254
+ | `fred-runtime` | [pypi](https://pypi.org/project/fred-runtime/) | This package |
240
255
 
241
256
  ---
242
257
 
@@ -39,7 +39,7 @@ from typing import Any, Literal
39
39
 
40
40
  import yaml
41
41
  from fred_sdk.contracts.models import MCPServerConfiguration
42
- from pydantic import BaseModel, ConfigDict, Field
42
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
43
43
 
44
44
  from .config import AgentPodConfig
45
45
 
@@ -114,6 +114,36 @@ class _McpCatalog(_CatalogFile):
114
114
  version: Literal["v1"] = "v1"
115
115
  servers: list[MCPServerConfiguration] = Field(default_factory=list)
116
116
 
117
+ @model_validator(mode="after")
118
+ def _reject_duplicate_server_ids(self) -> "_McpCatalog":
119
+ """
120
+ Reject duplicate MCP server ids in one catalog.
121
+
122
+ Why this exists:
123
+ - the managed-agent contract now stores per-server config keyed by MCP
124
+ server id, so duplicates would make selection and config resolution
125
+ ambiguous and unsafe
126
+
127
+ How to use it:
128
+ - triggered automatically during `_McpCatalog.model_validate(...)`
129
+
130
+ Example:
131
+ - `load_mcp_catalog("./config/mcp_catalog.yaml")`
132
+ """
133
+
134
+ seen: set[str] = set()
135
+ duplicates: list[str] = []
136
+ for server in self.servers:
137
+ if server.id in seen and server.id not in duplicates:
138
+ duplicates.append(server.id)
139
+ seen.add(server.id)
140
+ if duplicates:
141
+ duplicates_text = ", ".join(repr(server_id) for server_id in duplicates)
142
+ raise ValueError(
143
+ f"Duplicate MCP server id(s) in catalog: {duplicates_text}"
144
+ )
145
+ return self
146
+
117
147
 
118
148
  def _load_yaml_mapping(path: Path) -> dict[str, Any]:
119
149
  """