fastworkflow 2.15.5__py3-none-any.whl → 2.17.13__py3-none-any.whl

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 (42) hide show
  1. fastworkflow/_workflows/command_metadata_extraction/_commands/ErrorCorrection/you_misunderstood.py +1 -1
  2. fastworkflow/_workflows/command_metadata_extraction/_commands/IntentDetection/what_can_i_do.py +16 -2
  3. fastworkflow/_workflows/command_metadata_extraction/_commands/wildcard.py +27 -570
  4. fastworkflow/_workflows/command_metadata_extraction/intent_detection.py +360 -0
  5. fastworkflow/_workflows/command_metadata_extraction/parameter_extraction.py +411 -0
  6. fastworkflow/chat_session.py +379 -206
  7. fastworkflow/cli.py +80 -165
  8. fastworkflow/command_context_model.py +73 -7
  9. fastworkflow/command_executor.py +14 -5
  10. fastworkflow/command_metadata_api.py +106 -6
  11. fastworkflow/examples/fastworkflow.env +2 -1
  12. fastworkflow/examples/fastworkflow.passwords.env +2 -1
  13. fastworkflow/examples/retail_workflow/_commands/exchange_delivered_order_items.py +32 -3
  14. fastworkflow/examples/retail_workflow/_commands/find_user_id_by_email.py +6 -5
  15. fastworkflow/examples/retail_workflow/_commands/modify_pending_order_items.py +32 -3
  16. fastworkflow/examples/retail_workflow/_commands/return_delivered_order_items.py +13 -2
  17. fastworkflow/examples/retail_workflow/_commands/transfer_to_human_agents.py +1 -1
  18. fastworkflow/intent_clarification_agent.py +131 -0
  19. fastworkflow/mcp_server.py +3 -3
  20. fastworkflow/run/__main__.py +33 -40
  21. fastworkflow/run_fastapi_mcp/README.md +373 -0
  22. fastworkflow/run_fastapi_mcp/__main__.py +1300 -0
  23. fastworkflow/run_fastapi_mcp/conversation_store.py +391 -0
  24. fastworkflow/run_fastapi_mcp/jwt_manager.py +341 -0
  25. fastworkflow/run_fastapi_mcp/mcp_specific.py +103 -0
  26. fastworkflow/run_fastapi_mcp/redoc_2_standalone_html.py +40 -0
  27. fastworkflow/run_fastapi_mcp/utils.py +517 -0
  28. fastworkflow/train/__main__.py +1 -1
  29. fastworkflow/utils/chat_adapter.py +99 -0
  30. fastworkflow/utils/python_utils.py +4 -4
  31. fastworkflow/utils/react.py +258 -0
  32. fastworkflow/utils/signatures.py +338 -139
  33. fastworkflow/workflow.py +1 -5
  34. fastworkflow/workflow_agent.py +185 -133
  35. {fastworkflow-2.15.5.dist-info → fastworkflow-2.17.13.dist-info}/METADATA +16 -18
  36. {fastworkflow-2.15.5.dist-info → fastworkflow-2.17.13.dist-info}/RECORD +40 -30
  37. fastworkflow/run_agent/__main__.py +0 -294
  38. fastworkflow/run_agent/agent_module.py +0 -194
  39. /fastworkflow/{run_agent → run_fastapi_mcp}/__init__.py +0 -0
  40. {fastworkflow-2.15.5.dist-info → fastworkflow-2.17.13.dist-info}/LICENSE +0 -0
  41. {fastworkflow-2.15.5.dist-info → fastworkflow-2.17.13.dist-info}/WHEEL +0 -0
  42. {fastworkflow-2.15.5.dist-info → fastworkflow-2.17.13.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,373 @@
1
+ # FastWorkflow FastAPI + MCP Service
2
+
3
+ HTTP + MCP interface for FastWorkflow workflows with synchronous and streaming execution.
4
+
5
+ ## Overview
6
+
7
+ This service exposes FastWorkflow workflows as REST endpoints and as MCP tools, enabling clients to:
8
+ - Initialize workflow sessions per channel
9
+ - Submit natural language queries (agent mode)
10
+ - Execute deterministic commands (assistant mode)
11
+ - Perform explicit actions
12
+ - Manage conversations with persistent history
13
+ - Collect feedback on interactions
14
+
15
+ ## Architecture
16
+
17
+ - **Session Management**: In-memory `ChannelSessionManager` with per-channel `ChatSession` instances
18
+ - **Persistence**: Rdict-backed conversation storage (one DB file per channel)
19
+ - **Execution**: Synchronous turn-based processing with queue-based communication
20
+ - **Tracing**: Traces are collected by default and included in synchronous responses or emitted incrementally during streaming
21
+ - **Streaming (REST)**: `/invoke_agent_stream` supports Streamable HTTP via NDJSON by default and SSE when requested in REST initialize
22
+ - **Streaming (MCP)**: MCP transport mounted at `/mcp`; tools stream partials via MCP transport by default or SSE when requested in MCP initialize
23
+
24
+ See [`docs/fastworkflow_fastapi_spec.md`](../../docs/fastworkflow_fastapi_spec.md) and [`docs/fastworkflow_fastapi_architecture.md`](../../docs/fastworkflow_fastapi_architecture.md) for complete specification and design.
25
+
26
+ ## Running the Service
27
+
28
+ ### Start Server (REST + MCP)
29
+
30
+ ```bash
31
+ uvicorn services.run_fastapi.main:app --host 0.0.0.0 --port 8000
32
+
33
+ # MCP (auto-mounted via fastapi_mcp) will be available at `/mcp`.
34
+ ```
35
+
36
+ ### Access Documentation
37
+
38
+ Once running, visit:
39
+ - **Swagger UI**: http://localhost:8000/docs
40
+ - **ReDoc**: http://localhost:8000/redoc
41
+ - **Health Check**: http://localhost:8000/
42
+
43
+ ## Environment Variables
44
+
45
+ Configure in your environment (loaded at process startup via CLI args or env load):
46
+
47
+ | Variable | Description | Required | Default |
48
+ |----------|-------------|----------|---------|
49
+ | `SPEEDDICT_FOLDERNAME` | Base folder for workflow contexts and conversation storage | Yes | - |
50
+ | `--expect_encrypted_jwt` | Enable full JWT signature verification (pass flag to require signed tokens) | No | False (no verification by default) |
51
+
52
+ Notes:
53
+ - Conversation DBs are stored under `SPEEDDICT_FOLDERNAME/channel_conversations` (directory is auto-created).
54
+ - `/conversations` now accepts a `limit` query parameter (default `20`).
55
+ - Shutdown waits up to 30 seconds for active turns (hard-coded).
56
+
57
+ ## Auth Modes
58
+
59
+ ### Trusted Mode (default): No Signature Verification
60
+ When `--expect_encrypted_jwt` is NOT set (trusted environments), the service still creates and returns JWT tokens from `/initialize`, but signature verification is disabled. Clients must include `Authorization: Bearer <access_token>` on subsequent requests.
61
+
62
+ ```bash
63
+ uvicorn services.run_fastapi.main:app --workflow_path /path/to/workflow
64
+ ```
65
+
66
+ Notes (trusted mode):
67
+ - `/initialize` returns access/refresh tokens and, if a startup command/action is provided, also returns the startup `CommandOutput`.
68
+ - Subsequent endpoints require `Authorization: Bearer <access_token>`.
69
+ - Traces include `user_id` when available (from JWT `uid` claim).
70
+
71
+ ### Secure Mode: Signed JWTs with Verification
72
+ For production deployments requiring full RSA signature verification:
73
+
74
+ ```bash
75
+ uvicorn services.run_fastapi.main:app --workflow_path /path/to/workflow --expect_encrypted_jwt
76
+ ```
77
+
78
+ **Secure mode** (with `--expect_encrypted_jwt` flag):
79
+ - `/initialize` issues access/refresh tokens. Subsequent endpoints require `Authorization: Bearer <token>`.
80
+ - JWT claims include `sub` (channel_id) and `uid` (user_id when provided).
81
+ - Tokens are verified (signature, expiry, audience/issuer). Invalid or expired tokens are rejected.
82
+ - Recommended for production deployments in untrusted environments
83
+
84
+ ### Token Access in Workflow Context
85
+
86
+ In secure mode, JWT tokens are passed to workflows via `workflow_context['http_bearer_token']` to support authenticated upstream calls. In trusted mode, tokens are not created/returned and `http_bearer_token` is absent.
87
+
88
+ **Important notes:**
89
+ - The token is **only available to authenticated endpoints** (those using `get_session_and_ensure_runtime` dependency)
90
+ - The token is stored in the workflow context dictionary under the key `http_bearer_token`
91
+ - Token is **automatically updated** on every authenticated request, ensuring workflows always have the current valid token
92
+ - Token expiration is **automatically verified** by `verify_token()` in both secure mode (`--expect_encrypted_jwt` flag) and trusted network mode
93
+ - In secure mode: Full cryptographic signature verification + expiration checking
94
+ - In trusted network mode: Expiration checking is performed (signature verification disabled)
95
+ - Tokens should be treated as sensitive data and handled securely in workflows
96
+ - The `/initialize` endpoint is unauthenticated and does NOT provide a token to the workflow context; tokens are only available after calling `/initialize` and using the returned token in subsequent requests
97
+
98
+ **Example usage in workflow:**
99
+
100
+ ```python
101
+ # In workflow code
102
+ workflow_context = self._context
103
+ bearer_token = workflow_context.get('http_bearer_token')
104
+
105
+ # Use token for API calls
106
+ headers = {"Authorization": f"Bearer {bearer_token}"}
107
+ response = requests.get("https://api.example.com/data", headers=headers)
108
+ ```
109
+
110
+ ## API Endpoints (REST)
111
+
112
+ ### `POST /initialize`
113
+ Initialize a session for a channel. Workflow configuration is loaded at server startup from CLI args/env.
114
+
115
+ **Request:**
116
+ ```json
117
+ {
118
+ "channel_id": "channel-123",
119
+ "user_id": "user-9",
120
+ "stream_format": "ndjson",
121
+ "startup_command": "load_workflow ...",
122
+ "startup_action": {
123
+ "command_name": "find_orders",
124
+ "parameters": {"channel_id": 42}
125
+ }
126
+ }
127
+ ```
128
+
129
+ **Rules:**
130
+ - `channel_id` is required.
131
+ - Exactly one of `startup_command` or `startup_action` may be provided (or neither).
132
+ - If startup is provided, `user_id` is required and recorded in the initial trace.
133
+ - `stream_format` controls REST streaming format for `/invoke_agent_stream` (NDJSON default, SSE optional).
134
+
135
+ **Response:**
136
+ ```json
137
+ {
138
+ "access_token": "eyJhbGci...",
139
+ "refresh_token": "eyJhbGci...",
140
+ "token_type": "bearer",
141
+ "expires_in": 3600,
142
+ "startup_output": { /* CommandOutput, present only if startup was executed */ }
143
+ }
144
+ ```
145
+
146
+ ### `POST /invoke_agent`
147
+ Submit a natural language query for agentic processing.
148
+
149
+ **Headers:**
150
+ - `Authorization: Bearer <access_token>` (JWT contains `sub` for channel_id and optional `uid` for user_id)
151
+
152
+ **Request:**
153
+ ```json
154
+ {
155
+ "user_query": "find orders for channel 42",
156
+ "timeout_seconds": 60
157
+ }
158
+ ```
159
+
160
+ **Response:**
161
+ ```json
162
+ {
163
+ "command_responses": [
164
+ {
165
+ "response": "Found 3 orders for channel 42",
166
+ "success": true,
167
+ "artifacts": {},
168
+ "next_actions": [],
169
+ "recommendations": []
170
+ }
171
+ ],
172
+ "workflow_name": "default_workflow",
173
+ "context": "Order management context",
174
+ "command_name": "find_orders",
175
+ "command_parameters": "channel_id=42",
176
+ "traces": [...]
177
+ }
178
+ ```
179
+
180
+ ### `POST /invoke_assistant`
181
+ Submit a query for deterministic/assistant execution (no planning).
182
+
183
+ Same request/response format as `/invoke_agent`.
184
+
185
+ ### `POST /perform_action`
186
+ Execute a specific workflow action directly (bypasses parameter extraction).
187
+
188
+ **Headers:**
189
+ - `Authorization: Bearer <access_token>` (JWT contains `sub` for channel_id and optional `uid` for user_id)
190
+
191
+ **Request:**
192
+ ```json
193
+ {
194
+ "action": {
195
+ "command_name": "find_orders",
196
+ "parameters": {"channel_id": 42}
197
+ },
198
+ "timeout_seconds": 60
199
+ }
200
+ ```
201
+
202
+ **Response:**
203
+ Same format as `/invoke_agent` (CommandOutput with traces).
204
+
205
+ ### `POST /invoke_agent_stream`
206
+ Stream trace events and final `CommandOutput` via Streamable HTTP:
207
+ - NDJSON (default; `Content-Type: application/x-ndjson`)
208
+ - SSE (when REST `stream_format` is set to `sse`; `Content-Type: text/event-stream`)
209
+
210
+ **Headers:** Same as `/invoke_agent`.
211
+
212
+ ## Conversation Management (REST)
213
+
214
+ ### `POST /new_conversation`
215
+ Persist current conversation and start a new one.
216
+
217
+ **Request:**
218
+ ```json
219
+ {}
220
+ ```
221
+
222
+ **Response:**
223
+ ```json
224
+ {
225
+ "status": "ok"
226
+ }
227
+ ```
228
+
229
+ ### `GET /conversations?channel_id={channel_id}&limit=20`
230
+ List conversations for a channel (most recent first). `limit` is optional; defaults to `20`.
231
+
232
+ **Response:**
233
+ ```json
234
+ [
235
+ {
236
+ "conversation_id": 1,
237
+ "topic": "Order Management",
238
+ "summary": "...",
239
+ "created_at": 1234567890000,
240
+ "updated_at": 1234567890000
241
+ }
242
+ ]
243
+ ```
244
+
245
+ ### `POST /activate_conversation`
246
+ Switch to a different conversation by ID.
247
+
248
+ **Request:**
249
+ ```json
250
+ {
251
+ "conversation_id": 1
252
+ }
253
+ ```
254
+
255
+ ### `POST /post_feedback`
256
+ Attach feedback to the latest turn.
257
+
258
+ **Request:**
259
+ ```json
260
+ {
261
+ "binary_or_numeric_score": true,
262
+ "nl_feedback": "Helpful response"
263
+ }
264
+ ```
265
+
266
+ At least one of `binary_or_numeric_score` or `nl_feedback` must be provided.
267
+
268
+ ## Admin Endpoints (REST-only; not exposed via MCP)
269
+
270
+ ### `POST /admin/dump_all_conversations`
271
+ Export all conversations to JSONL.
272
+
273
+ **Request:**
274
+ ```json
275
+ {
276
+ "output_folder": "/path/to/export"
277
+ }
278
+ ```
279
+
280
+ **Response:**
281
+ ```json
282
+ {
283
+ "file_path": "/path/to/export/all_conversations_1234567890.jsonl"
284
+ }
285
+ ```
286
+
287
+ ## Usage Examples
288
+
289
+ ### REST initialize
290
+ ```python
291
+ import requests
292
+
293
+ resp = requests.post("http://localhost:8000/initialize", json={
294
+ "channel_id": "alice",
295
+ "stream_format": "ndjson"
296
+ })
297
+ print(resp.json()) # {"access_token": "...", "refresh_token": "...", "token_type": "bearer", "expires_in": 3600}
298
+ ```
299
+
300
+ ### REST sync invoke
301
+ ```python
302
+ # First get a token from /initialize
303
+ init_resp = requests.post("http://localhost:8000/initialize", json={
304
+ "channel_id": "alice",
305
+ "stream_format": "ndjson"
306
+ })
307
+ token_data = init_resp.json()
308
+ access_token = token_data["access_token"]
309
+
310
+ # Then use the token for authenticated requests
311
+ resp = requests.post("http://localhost:8000/invoke_agent",
312
+ headers={"Authorization": f"Bearer {access_token}"},
313
+ json={
314
+ "channel_query": "list all channels",
315
+ "timeout_seconds": 30
316
+ }
317
+ )
318
+ result = resp.json()
319
+ print(result["command_responses"])
320
+ print(result.get("traces"))
321
+ ```
322
+
323
+ ### MCP Quickstart
324
+ - Mount is available at `/mcp` (auto-exposed by fastapi_mcp).
325
+ - In secure mode, MCP clients use pre-configured long-lived access tokens (generated via `/admin/generate_mcp_token`).
326
+ - In trusted mode, clients must send `Authorization: Bearer <token>`; the JWT `sub` claim carries the `channel_id`.
327
+ - No need for initialize or refresh_token tools in MCP context.
328
+
329
+ MCP invoke agent (streaming):
330
+
331
+ ```bash
332
+ # NDJSON (default for MCP)
333
+ curl -N -X POST http://localhost:8000/mcp/invoke_agent \
334
+ -H 'Content-Type: application/json' \
335
+ -H 'Accept: application/x-ndjson' \
336
+ -H 'Authorization: Bearer <your-mcp-token>' \
337
+ -d '{"channel_query":"find orders for channel 42","timeout_seconds":60}'
338
+
339
+ # SSE (if stream_format was set to "sse" during MCP setup)
340
+ curl -N -X POST http://localhost:8000/mcp/invoke_agent \
341
+ -H 'Content-Type: application/json' \
342
+ -H 'Accept: text/event-stream' \
343
+ -H 'Authorization: Bearer <your-mcp-token>' \
344
+ -d '{"channel_query":"find orders for channel 42","timeout_seconds":60}'
345
+ ```
346
+
347
+ ### MCP Prompts
348
+ The MCP mount registers two prompts for client discovery:
349
+ - `format-command(intent, metadata)`
350
+ - `clarify-params(error_message, metadata)`
351
+
352
+ ## Testing
353
+
354
+ See [`tests/`](../../tests/) for unit and integration tests.
355
+
356
+ **Key test scenarios:**
357
+ - SessionManager concurrency and lifecycle
358
+ - Env loading from files only
359
+ - CLI argument validation (startup_command vs startup_action)
360
+ - Timeout behavior (504 on no output)
361
+ - Conversation persistence and listing
362
+ - Feedback attachment
363
+ - Initialize with startup command/action returns `startup_output` and records conversation
364
+ - Both trusted mode return tokens; secure mode tokens are encrypted
365
+ - Traces include `user_id` and `raw_command`
366
+
367
+ ## Future Enhancements
368
+
369
+ - Session TTL and eviction policy
370
+ - Richer observability and structured logging
371
+ - Security: workflow path allow-list, authn/z
372
+ - Conversation history restoration on session resume
373
+