agent-framework-ag-ui 1.2.2__tar.gz → 1.3.0__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 (104) hide show
  1. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/AGENTS.md +9 -0
  2. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/PKG-INFO +27 -8
  3. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/README.md +24 -5
  4. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/__init__.py +4 -1
  5. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_agent.py +28 -0
  6. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_agent_run.py +261 -44
  7. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_approval_lifecycle.py +69 -2
  8. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_approval_state.py +2 -0
  9. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_client.py +86 -25
  10. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_endpoint.py +5 -1
  11. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_message_adapters.py +423 -59
  12. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_run_common.py +57 -29
  13. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_snapshot_session.py +2 -2
  14. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_snapshots.py +34 -2
  15. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_state.py +43 -2
  16. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_types.py +10 -2
  17. agent_framework_ag_ui-1.3.0/agent_framework_ag_ui/_utils.py +519 -0
  18. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_workflow.py +38 -18
  19. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_workflow_run.py +90 -14
  20. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/pyproject.toml +3 -3
  21. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_ag_ui_client.py +258 -17
  22. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_endpoint.py +1010 -10
  23. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_message_adapters.py +1150 -0
  24. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_public_exports.py +5 -3
  25. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_run.py +130 -0
  26. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_run_common.py +376 -1
  27. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_snapshot_session.py +32 -0
  28. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_snapshots.py +69 -0
  29. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_workflow_run.py +186 -4
  30. agent_framework_ag_ui-1.2.2/agent_framework_ag_ui/_utils.py +0 -285
  31. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/.gitignore +0 -0
  32. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/LICENSE +0 -0
  33. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_a2ui/__init__.py +0 -0
  34. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_a2ui/_agent.py +0 -0
  35. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_a2ui/_factory.py +0 -0
  36. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_a2ui/_state.py +0 -0
  37. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_event_converters.py +0 -0
  38. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_feature_usage.py +0 -0
  39. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_http_service.py +0 -0
  40. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_predictive_state.py +0 -0
  41. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/_tooling.py +0 -0
  42. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui/py.typed +0 -0
  43. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/.env.example +0 -0
  44. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/.vscode/settings.json +0 -0
  45. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/README.md +0 -0
  46. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/__init__.py +0 -0
  47. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/__main__.py +0 -0
  48. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/__init__.py +0 -0
  49. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/a2ui_agents.py +0 -0
  50. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/document_writer_agent.py +0 -0
  51. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/human_in_the_loop_agent.py +0 -0
  52. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/recipe_agent.py +0 -0
  53. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/research_assistant_agent.py +0 -0
  54. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/simple_agent.py +0 -0
  55. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/subgraphs_agent.py +0 -0
  56. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/task_planner_agent.py +0 -0
  57. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/task_steps_agent.py +0 -0
  58. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/ui_generator_agent.py +0 -0
  59. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/weather_agent.py +0 -0
  60. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/agents/weather_state_agent.py +0 -0
  61. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/server/__init__.py +0 -0
  62. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/server/api/backend_tool_rendering.py +0 -0
  63. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/agent_framework_ag_ui_examples/server/main.py +0 -0
  64. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/getting_started/README.md +0 -0
  65. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/getting_started/client.py +0 -0
  66. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/getting_started/client_advanced.py +0 -0
  67. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/getting_started/client_with_agent.py +0 -0
  68. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/getting_started/server.py +0 -0
  69. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/conftest.py +0 -0
  70. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/event_stream.py +0 -0
  71. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/golden/__init__.py +0 -0
  72. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/golden/conftest.py +0 -0
  73. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/golden/test_scenario_agentic_chat.py +0 -0
  74. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/golden/test_scenario_backend_tools.py +0 -0
  75. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/golden/test_scenario_deterministic_state.py +0 -0
  76. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/golden/test_scenario_generative_ui_agent.py +0 -0
  77. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/golden/test_scenario_generative_ui_tool.py +0 -0
  78. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/golden/test_scenario_hitl.py +0 -0
  79. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/golden/test_scenario_predictive_state.py +0 -0
  80. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/golden/test_scenario_shared_state.py +0 -0
  81. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/golden/test_scenario_subgraphs.py +0 -0
  82. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/golden/test_scenario_workflow.py +0 -0
  83. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/sse_helpers.py +0 -0
  84. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_a2ui.py +0 -0
  85. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_agent_wrapper_comprehensive.py +0 -0
  86. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_approval_lifecycle.py +0 -0
  87. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_approval_result_event.py +0 -0
  88. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_approval_state.py +0 -0
  89. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_confirm_changes_snapshot.py +0 -0
  90. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_event_converters.py +0 -0
  91. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_forwarded_props_in_metadata.py +0 -0
  92. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_handoff_replay.py +0 -0
  93. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_http_round_trip.py +0 -0
  94. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_http_service.py +0 -0
  95. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_message_hygiene.py +0 -0
  96. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_multi_turn.py +0 -0
  97. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_predictive_state.py +0 -0
  98. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_service_thread_id.py +0 -0
  99. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_structured_output.py +0 -0
  100. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_subgraphs_example_agent.py +0 -0
  101. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_tooling.py +0 -0
  102. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_types.py +0 -0
  103. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_utils.py +0 -0
  104. {agent_framework_ag_ui-1.2.2 → agent_framework_ag_ui-1.3.0}/tests/ag_ui/test_workflow_agent.py +0 -0
@@ -8,6 +8,8 @@ AG-UI protocol integration for building agent UIs with the AG-UI standard.
8
8
  - **`AgentFrameworkWorkflow`** - Wraps native `Workflow` objects, or accepts `workflow_factory(thread_id)` for thread-scoped workflow instances without subclassing
9
9
  - **`AGUIChatClient`** - Chat client that speaks AG-UI protocol
10
10
  - **`AGUIHttpService`** - HTTP service for AG-UI endpoints
11
+ - **`agent_framework_messages_to_agui_host_history()`** - Converts persisted Agent Framework messages to bounded
12
+ AG-UI Host history while retaining MCP widget payloads and model replay metadata
11
13
  - **`AGUIEventConverter`** - Converts between Agent Framework and AG-UI events
12
14
  - **`add_agent_framework_fastapi_endpoint()`** - Add AG-UI endpoint to FastAPI app (`SupportsAgentRun` or `Workflow`)
13
15
  - **`InMemoryAGUIThreadSnapshotStore`** - Memory-only latest AG-UI Thread Snapshot store for local development, demos, and tests
@@ -50,6 +52,13 @@ AG-UI protocol integration for building agent UIs with the AG-UI standard.
50
52
  - AG-UI Thread and Run ids are client-owned protocol correlation ids. Service-session mode stores provider conversation
51
53
  or response ids privately in the thread snapshot. Set `service_session_id_from_thread_id=True` only for compatibility
52
54
  when the application intentionally uses a provider continuation id as its AG-UI Thread id.
55
+ - A configured Snapshot Scope and the client-owned Thread id are combined into a deterministic internal
56
+ `AgentSession.session_id`. Keep the raw Thread id for protocol events and snapshot addressing so equal Thread ids
57
+ in different trusted scopes cannot collide in context-provider state. The deprecated
58
+ `legacy_session_id_from_thread_id=True` compatibility option preserves raw provider keys only for explicit
59
+ migrations and must warn because it disables that isolation; it is unsafe for shared multi-tenant deployments.
60
+ A configured endpoint resolver must return a non-empty string. Reject invalid results before accessing state or
61
+ invoking the runner; absence of a resolver, not an invalid result, selects intentionally unscoped operation.
53
62
  - `confirm_changes` snapshot cleanup resolves the synthetic confirmation back to its original `function_call_id`;
54
63
  it must never concatenate unrelated tool results or record accepted changes without a matching real result.
55
64
  - SSE keepalive is endpoint-owned transport behavior configured through
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: agent-framework-ag-ui
3
- Version: 1.2.2
3
+ Version: 1.3.0
4
4
  Summary: AG-UI protocol integration for Agent Framework
5
5
  Project-URL: homepage, https://aka.ms/agent-framework
6
6
  Project-URL: source, https://github.com/microsoft/agent-framework/tree/main/python
@@ -19,8 +19,8 @@ Classifier: Programming Language :: Python :: 3.13
19
19
  Classifier: Typing :: Typed
20
20
  Requires-Python: >=3.10
21
21
  Requires-Dist: ag-ui-protocol<0.2,>=0.1.19
22
- Requires-Dist: agent-framework-core<2,>=1.17.0
23
- Requires-Dist: fastapi<0.140.0,>=0.121.0
22
+ Requires-Dist: agent-framework-core<2,>=1.18.0
23
+ Requires-Dist: fastapi<0.142.0,>=0.121.0
24
24
  Requires-Dist: httpx<1,>=0.28.1
25
25
  Requires-Dist: sse-starlette<4,>=3.4.5
26
26
  Requires-Dist: uvicorn[standard]<1,>=0.30.0
@@ -271,12 +271,14 @@ Review focus: whether these names are the right stable contract for Python users
271
271
 
272
272
  | Surface | Public exports |
273
273
  | --- | --- |
274
- | `agent_framework.ag_ui` facade | `AgentFrameworkAgent`, `AgentFrameworkWorkflow`, `AGUIChatClient`, `AGUIEventConverter`, `AGUIHttpService`, `AGUIThreadSnapshot`, `AGUIThreadSnapshotStore`, `InMemoryAGUIThreadSnapshotStore`, `SnapshotScopeResolver`, `add_agent_framework_fastapi_endpoint`, `state_update`, `__version__` |
274
+ | `agent_framework.ag_ui` facade | `AgentFrameworkAgent`, `AgentFrameworkWorkflow`, `AGUIChatClient`, `AGUIEventConverter`, `AGUIHttpService`, `AGUIThreadSnapshot`, `AGUIThreadSnapshotStore`, `InMemoryAGUIThreadSnapshotStore`, `SnapshotScopeResolver`, `add_agent_framework_fastapi_endpoint`, `state_carrier`, `state_update`, `__version__` |
275
275
  | Direct `agent_framework_ag_ui` package | Facade exports plus `AGUIChatOptions`, `AGUIRequest`, `AGUIThreadID`, `AgentState`, `DEFAULT_MAX_THREAD_SNAPSHOTS`, `DEFAULT_TAGS`, `PredictStateConfig`, `RunMetadata`, `SnapshotScope`, `WorkflowFactory` |
276
276
  | AG-UI protocol package (`ag_ui.core`) | `Interrupt`, `ResumeEntry`, `RunFinishedInterruptOutcome`, and related run outcome models |
277
277
 
278
278
  Interrupt support is protocol data rather than a separate Agent Framework Python class. Requests accept canonical `availableInterrupts`/`available_interrupts` and `resume` values; `AGUIChatClient` and `AGUIHttpService.post_run(...)` forward those fields with AG-UI wire aliases; agent approval and workflow `request_info` pauses emit `RUN_FINISHED.outcome.interrupts`; `AGUIEventConverter` preserves canonical interrupt outcome metadata on the final `ChatResponseUpdate`; and thread snapshot hydration replays the canonical interrupt outcome when a scoped snapshot stores an unresolved pause.
279
279
 
280
+ Use `state_carrier(...)` to mark JSON content that should be sent in the AG-UI request's `state` field rather than as a model-visible document. The client removes explicitly marked carriers from all client-controlled history and uses the most recent carrier. Ordinary `application/json` content remains a document. For migration, pass `allow_legacy_state_carrier=True` in `AGUIChatOptions` to recognize the deprecated final single-content base64 JSON convention; mixed text and document messages remain model-visible. This client-only option emits a `DeprecationWarning` when the legacy convention is used and is not sent to the remote server.
281
+
280
282
  ## Features
281
283
 
282
284
  This integration supports all 7 AG-UI features:
@@ -410,10 +412,27 @@ A frontend can then hydrate the latest stored snapshot for the scoped thread:
410
412
 
411
413
  Endpoint configuration requires `snapshot_scope_resolver` whenever a snapshot store is configured, including when
412
414
  the store is already set on a pre-wrapped `AgentFrameworkAgent` or `AgentFrameworkWorkflow`. The resolver returns
413
- the application-defined Snapshot Scope used with the AG-UI Thread id as the storage key. When using
414
- `AgentFrameworkWorkflow(workflow_factory=...)`, the same resolver also scopes the in-memory workflow cache even
415
- without a snapshot store; provide it in multi-user deployments so two users who submit the same `threadId` do not
416
- share a live `Workflow` instance.
415
+ the application-defined Snapshot Scope used with the AG-UI Thread id as the storage key. The endpoint also derives
416
+ the internal `AgentSession.session_id` from this trusted scope and the client-owned Thread id, so context providers
417
+ cannot merge server-side state for equal Thread ids in different scopes. The raw Thread id remains unchanged in
418
+ AG-UI events and snapshot operations. When using `AgentFrameworkWorkflow(workflow_factory=...)`, the same resolver
419
+ also scopes the in-memory workflow cache even without a snapshot store; provide it in multi-user deployments so two
420
+ users who submit the same `threadId` do not share a live `Workflow` instance.
421
+
422
+ Authenticate and authorize the current scope on every request, including hydration and approval resume, rather than
423
+ trusting a scope supplied through Shared State or forwarded properties. A configured resolver must return a non-empty
424
+ string. Returning `None`, an empty string, or another type fails the request with a generic HTTP 500 configuration
425
+ error before accessing snapshots, approval state, or context providers. Resolver failures never fall back to unscoped
426
+ operation. Valid scope strings are used exactly as returned, without trimming or normalization. An endpoint without a
427
+ resolver remains intentionally unscoped; it must not share session-keyed storage across distinct authorization scopes.
428
+ Use endpoint authentication dependencies to reject unauthorized requests before scope resolution.
429
+
430
+ Existing applications that need time to migrate provider records from raw Thread-id keys can temporarily wrap the
431
+ agent with `AgentFrameworkAgent(..., legacy_session_id_from_thread_id=True)`. This deprecated compatibility option
432
+ emits a `DeprecationWarning` and disables Snapshot Scope isolation for context-provider state. It is not safe for a
433
+ shared multi-tenant deployment, even with a trusted resolver. Keep it disabled when establishing scope isolation.
434
+
435
+ ### Request state and snapshot authority
417
436
 
418
437
  For hosted agents, request Shared State is also available through `AgentSession.state` during that run, whether or
419
438
  not snapshot persistence is configured. Request values are untrusted per-run context: they overlay ordinary restored
@@ -239,12 +239,14 @@ Review focus: whether these names are the right stable contract for Python users
239
239
 
240
240
  | Surface | Public exports |
241
241
  | --- | --- |
242
- | `agent_framework.ag_ui` facade | `AgentFrameworkAgent`, `AgentFrameworkWorkflow`, `AGUIChatClient`, `AGUIEventConverter`, `AGUIHttpService`, `AGUIThreadSnapshot`, `AGUIThreadSnapshotStore`, `InMemoryAGUIThreadSnapshotStore`, `SnapshotScopeResolver`, `add_agent_framework_fastapi_endpoint`, `state_update`, `__version__` |
242
+ | `agent_framework.ag_ui` facade | `AgentFrameworkAgent`, `AgentFrameworkWorkflow`, `AGUIChatClient`, `AGUIEventConverter`, `AGUIHttpService`, `AGUIThreadSnapshot`, `AGUIThreadSnapshotStore`, `InMemoryAGUIThreadSnapshotStore`, `SnapshotScopeResolver`, `add_agent_framework_fastapi_endpoint`, `state_carrier`, `state_update`, `__version__` |
243
243
  | Direct `agent_framework_ag_ui` package | Facade exports plus `AGUIChatOptions`, `AGUIRequest`, `AGUIThreadID`, `AgentState`, `DEFAULT_MAX_THREAD_SNAPSHOTS`, `DEFAULT_TAGS`, `PredictStateConfig`, `RunMetadata`, `SnapshotScope`, `WorkflowFactory` |
244
244
  | AG-UI protocol package (`ag_ui.core`) | `Interrupt`, `ResumeEntry`, `RunFinishedInterruptOutcome`, and related run outcome models |
245
245
 
246
246
  Interrupt support is protocol data rather than a separate Agent Framework Python class. Requests accept canonical `availableInterrupts`/`available_interrupts` and `resume` values; `AGUIChatClient` and `AGUIHttpService.post_run(...)` forward those fields with AG-UI wire aliases; agent approval and workflow `request_info` pauses emit `RUN_FINISHED.outcome.interrupts`; `AGUIEventConverter` preserves canonical interrupt outcome metadata on the final `ChatResponseUpdate`; and thread snapshot hydration replays the canonical interrupt outcome when a scoped snapshot stores an unresolved pause.
247
247
 
248
+ Use `state_carrier(...)` to mark JSON content that should be sent in the AG-UI request's `state` field rather than as a model-visible document. The client removes explicitly marked carriers from all client-controlled history and uses the most recent carrier. Ordinary `application/json` content remains a document. For migration, pass `allow_legacy_state_carrier=True` in `AGUIChatOptions` to recognize the deprecated final single-content base64 JSON convention; mixed text and document messages remain model-visible. This client-only option emits a `DeprecationWarning` when the legacy convention is used and is not sent to the remote server.
249
+
248
250
  ## Features
249
251
 
250
252
  This integration supports all 7 AG-UI features:
@@ -378,10 +380,27 @@ A frontend can then hydrate the latest stored snapshot for the scoped thread:
378
380
 
379
381
  Endpoint configuration requires `snapshot_scope_resolver` whenever a snapshot store is configured, including when
380
382
  the store is already set on a pre-wrapped `AgentFrameworkAgent` or `AgentFrameworkWorkflow`. The resolver returns
381
- the application-defined Snapshot Scope used with the AG-UI Thread id as the storage key. When using
382
- `AgentFrameworkWorkflow(workflow_factory=...)`, the same resolver also scopes the in-memory workflow cache even
383
- without a snapshot store; provide it in multi-user deployments so two users who submit the same `threadId` do not
384
- share a live `Workflow` instance.
383
+ the application-defined Snapshot Scope used with the AG-UI Thread id as the storage key. The endpoint also derives
384
+ the internal `AgentSession.session_id` from this trusted scope and the client-owned Thread id, so context providers
385
+ cannot merge server-side state for equal Thread ids in different scopes. The raw Thread id remains unchanged in
386
+ AG-UI events and snapshot operations. When using `AgentFrameworkWorkflow(workflow_factory=...)`, the same resolver
387
+ also scopes the in-memory workflow cache even without a snapshot store; provide it in multi-user deployments so two
388
+ users who submit the same `threadId` do not share a live `Workflow` instance.
389
+
390
+ Authenticate and authorize the current scope on every request, including hydration and approval resume, rather than
391
+ trusting a scope supplied through Shared State or forwarded properties. A configured resolver must return a non-empty
392
+ string. Returning `None`, an empty string, or another type fails the request with a generic HTTP 500 configuration
393
+ error before accessing snapshots, approval state, or context providers. Resolver failures never fall back to unscoped
394
+ operation. Valid scope strings are used exactly as returned, without trimming or normalization. An endpoint without a
395
+ resolver remains intentionally unscoped; it must not share session-keyed storage across distinct authorization scopes.
396
+ Use endpoint authentication dependencies to reject unauthorized requests before scope resolution.
397
+
398
+ Existing applications that need time to migrate provider records from raw Thread-id keys can temporarily wrap the
399
+ agent with `AgentFrameworkAgent(..., legacy_session_id_from_thread_id=True)`. This deprecated compatibility option
400
+ emits a `DeprecationWarning` and disables Snapshot Scope isolation for context-provider state. It is not safe for a
401
+ shared multi-tenant deployment, even with a trusted resolver. Keep it disabled when establishing scope isolation.
402
+
403
+ ### Request state and snapshot authority
385
404
 
386
405
  For hosted agents, request Shared State is also available through `AgentSession.state` during that run, whether or
387
406
  not snapshot persistence is configured. Request values are untrusted per-run context: they overlay ordinary restored
@@ -10,6 +10,7 @@ from ._client import AGUIChatClient
10
10
  from ._endpoint import add_agent_framework_fastapi_endpoint
11
11
  from ._event_converters import AGUIEventConverter
12
12
  from ._http_service import AGUIHttpService
13
+ from ._message_adapters import agent_framework_messages_to_agui_host_history
13
14
  from ._snapshots import (
14
15
  DEFAULT_MAX_THREAD_SNAPSHOTS,
15
16
  AGUIThreadID,
@@ -19,7 +20,7 @@ from ._snapshots import (
19
20
  SnapshotScope,
20
21
  SnapshotScopeResolver,
21
22
  )
22
- from ._state import state_update
23
+ from ._state import state_carrier, state_update
23
24
  from ._types import AgentState, AGUIChatOptions, AGUIRequest, PredictStateConfig, RunMetadata
24
25
  from ._workflow import AgentFrameworkWorkflow, WorkflowFactory
25
26
 
@@ -39,6 +40,7 @@ __all__ = [
39
40
  "AgentFrameworkWorkflow",
40
41
  "WorkflowFactory",
41
42
  "add_agent_framework_fastapi_endpoint",
43
+ "agent_framework_messages_to_agui_host_history",
42
44
  "AGUIChatClient",
43
45
  "AGUIChatOptions",
44
46
  "AGUIEventConverter",
@@ -55,6 +57,7 @@ __all__ = [
55
57
  "SnapshotScopeResolver",
56
58
  "DEFAULT_MAX_THREAD_SNAPSHOTS",
57
59
  "DEFAULT_TAGS",
60
+ "state_carrier",
58
61
  "state_update",
59
62
  "__version__",
60
63
  # A2UI (lazy — require ag-ui-a2ui-toolkit)
@@ -2,6 +2,7 @@
2
2
 
3
3
  """AgentFrameworkAgent wrapper for AG-UI protocol."""
4
4
 
5
+ import warnings
5
6
  from collections.abc import AsyncGenerator
6
7
  from typing import Any, cast
7
8
 
@@ -27,6 +28,8 @@ class AgentConfig:
27
28
  snapshot_store: AGUIThreadSnapshotStore | None = None,
28
29
  a2ui_config: dict[str, Any] | None = None,
29
30
  service_session_id_from_thread_id: bool = False,
31
+ emit_messages_snapshot: bool = True,
32
+ legacy_session_id_from_thread_id: bool = False,
30
33
  ):
31
34
  """Initialize agent configuration.
32
35
 
@@ -45,6 +48,11 @@ class AgentConfig:
45
48
  require_confirmation: Whether predictive updates require user confirmation before applying
46
49
  a2ui_config: Optional backend A2UI config consumed by auto-injection
47
50
  (``forwardedProps.injectA2UITool``). See ``plan_a2ui_injection``.
51
+ emit_messages_snapshot: Whether to emit a terminal MessagesSnapshotEvent at the end of runs.
52
+ Defaults to True for backward compatibility. Set to False when using HistoryProvider
53
+ to prevent redundant full-transcript rewrites on the client.
54
+ legacy_session_id_from_thread_id: Deprecated compatibility option that uses the client-owned
55
+ AG-UI Thread id directly as the internal Agent Session id.
48
56
  """
49
57
  self.state_schema = self._normalize_state_schema(state_schema)
50
58
  self.predict_state_config = predict_state_config or {}
@@ -53,6 +61,8 @@ class AgentConfig:
53
61
  self.require_confirmation = require_confirmation
54
62
  self.snapshot_store = snapshot_store
55
63
  self.a2ui_config = a2ui_config
64
+ self.emit_messages_snapshot = emit_messages_snapshot
65
+ self.legacy_session_id_from_thread_id = legacy_session_id_from_thread_id
56
66
 
57
67
  @staticmethod
58
68
  def _normalize_state_schema(state_schema: Any | None) -> dict[str, Any]:
@@ -101,6 +111,8 @@ class AgentFrameworkAgent:
101
111
  snapshot_store: AGUIThreadSnapshotStore | None = None,
102
112
  a2ui_config: dict[str, Any] | None = None,
103
113
  service_session_id_from_thread_id: bool = False,
114
+ emit_messages_snapshot: bool = True,
115
+ legacy_session_id_from_thread_id: bool = False,
104
116
  ):
105
117
  """Initialize the AG-UI compatible agent wrapper.
106
118
 
@@ -120,7 +132,21 @@ class AgentFrameworkAgent:
120
132
  snapshot_store: Optional AG-UI Thread Snapshot store. Snapshot persistence remains inactive unless
121
133
  endpoint setup also provides an explicit Snapshot Scope resolver.
122
134
  a2ui_config: Optional backend A2UI config consumed by auto-injection.
135
+ emit_messages_snapshot: Whether to emit a terminal MessagesSnapshotEvent at the end of runs.
136
+ Defaults to True. Set to False when using HistoryProvider.
137
+ legacy_session_id_from_thread_id: Deprecated compatibility option that uses the client-owned
138
+ AG-UI Thread id directly as the internal Agent Session id. This disables Snapshot Scope
139
+ isolation for context-provider state.
123
140
  """
141
+ if legacy_session_id_from_thread_id:
142
+ warnings.warn(
143
+ "legacy_session_id_from_thread_id=True is deprecated because client-owned AG-UI Thread ids "
144
+ "do not isolate server-side state. Migrate provider state to scoped session ids and remove "
145
+ "this option.",
146
+ DeprecationWarning,
147
+ stacklevel=2,
148
+ )
149
+
124
150
  self.agent = agent
125
151
  self.name = name or getattr(agent, "name", "agent")
126
152
  self.description = description or getattr(agent, "description", "")
@@ -133,6 +159,8 @@ class AgentFrameworkAgent:
133
159
  require_confirmation=require_confirmation,
134
160
  snapshot_store=snapshot_store,
135
161
  a2ui_config=a2ui_config,
162
+ emit_messages_snapshot=emit_messages_snapshot,
163
+ legacy_session_id_from_thread_id=legacy_session_id_from_thread_id,
136
164
  )
137
165
 
138
166
  # Server-side Approval State. Populated when approval requests are emitted