feat(advanced): release the advanced agent changes as 0.16.7.post3 - #1098
radu-mocanu wants to merge 9 commits into
Conversation
b877652 to
64ef583
Compare
There was a problem hiding this comment.
Note
Copilot was unable to run its full agentic suite in this review.
Pull request overview
This PR adds first-class support for output-file attachments (discovering file fields in output schemas, injecting a file-publishing tool, and verifying references at termination), while also hardening/expanding the advanced agent runtime (payload handling, max-iteration budgeting, chat attachment hydration, and an optional QuickJS code interpreter with a security-driven allowlist).
Changes:
- Introduces output-file discovery/prompting/verification, plus an internal
create_output_filetool and schema utilities for job attachments. - Adds
SUSPENDS_RUNtool metadata and tests to prevent suspending tools from being reachable via unsafe bridges (notably the code interpreter). - Refactors attachment+JSON utilities into shared modules and updates advanced agent wrapper behavior (runtime prompts, iteration caps, payload handling, and message attachment hydration).
Reviewed changes
Copilot reviewed 58 out of 62 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/runtime/test_chat_message_mapper_workspace.py | Removes standalone workspace/attachment mapping tests (coverage moved/changed elsewhere). |
| tests/runtime/test_chat_message_mapper.py | Adds coverage for assistant external-value attachment mapping. |
| tests/agent/tools/test_suspends_run_metadata.py | Adds AST-based contract test enforcing SUSPENDS_RUN stamping. |
| tests/agent/tools/internal_tools/test_output_file_tool.py | Adds tests for the internal output-file tool, schema, and path safety. |
| tests/agent/react/test_output_files_node.py | Adds tests for the termination gate verifying output file references. |
| tests/agent/react/test_json_utils.py | Updates imports after moving JSON helpers into attachments utilities. |
| tests/agent/attachments/test_output_files.py | Adds tests for output schema file-field discovery, prompting, and verification logic. |
| tests/agent/advanced/test_utils.py | Adds tests for message attachment hydration into workspace paths and attachment-block rendering. |
| tests/agent/advanced/test_payload_handler_middleware.py | Adds coverage for advanced-agent payload middleware (Gemini tool_config, stop reasons, empty answer rejection). |
| tests/agent/advanced/test_max_iterations.py | Adds coverage for per-turn iteration budgeting in advanced agents. |
| tests/agent/advanced/test_main_agent_only_tools.py | Adds contract test ensuring main-agent-only tools never reach subagents. |
| tests/agent/advanced/test_create_advanced_agent_graph.py | Expands wrapper-graph tests (runtime prompt middleware lookup, output-file verification node insertion). |
| tests/agent/advanced/test_create_advanced_agent.py | Updates expectations around built-in tools (files tools present; todo tool absent). |
| tests/agent/advanced/test_conversational_advanced_agent_graph.py | Adds conversational wrapper tests (runtime prompts, alias handling, attachment hydration, custom output extraction). |
| tests/agent/advanced/test_code_interpreter_replay.py | Adds end-to-end replay test validating why task() must be withheld when suspension is possible. |
| tests/agent/advanced/test_code_interpreter_persistence.py | Adds subprocess test for REPL persistence across process restarts via checkpointing. |
| tests/agent/advanced/test_code_interpreter.py | Adds comprehensive tests for code interpreter allowlist policy and sandbox behavior. |
| src/uipath_langchain/runtime/runtime.py | Updates client-side tool info import to a shared contracts module. |
| src/uipath_langchain/runtime/messages.py | Switches to shared attachments-block renderer and changes external-value mapping behavior. |
| src/uipath_langchain/agent/wrappers/job_attachment_wrapper.py | Moves attachment/JSON helper imports and reduces runtime imports via TYPE_CHECKING. |
| src/uipath_langchain/agent/tools/process_tool.py | Stamps SUSPENDS_RUN and updates job attachment helper import. |
| src/uipath_langchain/agent/tools/ixp_escalation_tool.py | Stamps SUSPENDS_RUN metadata on interrupting tool. |
| src/uipath_langchain/agent/tools/internal_tools/schema_utils.py | Extracts JOB_ATTACHMENT_DEFINITION and a reusable single_attachment_schema. |
| src/uipath_langchain/agent/tools/internal_tools/output_file_tool.py | Adds internal create_output_file tool supporting inline content and workspace file paths. |
| src/uipath_langchain/agent/tools/internal_tools/deeprag_tool.py | Stamps SUSPENDS_RUN metadata. |
| src/uipath_langchain/agent/tools/internal_tools/batch_transform_tool.py | Stamps SUSPENDS_RUN metadata. |
| src/uipath_langchain/agent/tools/internal_tools/analyze_files_tool.py | Updates job-attachment error helper import to shared module. |
| src/uipath_langchain/agent/tools/extraction_tool.py | Stamps SUSPENDS_RUN metadata and updates job attachment imports. |
| src/uipath_langchain/agent/tools/escalation_tool.py | Stamps SUSPENDS_RUN metadata. |
| src/uipath_langchain/agent/tools/context_tool.py | Stamps SUSPENDS_RUN metadata in relevant tool variants. |
| src/uipath_langchain/agent/tools/client_side_tool.py | Moves ClientSideToolInfo to shared contracts; stamps SUSPENDS_RUN. |
| src/uipath_langchain/agent/react/types.py | Adds output-file retries state, verification node enum, and config flag. |
| src/uipath_langchain/agent/react/router.py | Adds optional routing through VERIFY_OUTPUT_FILES for end_execution. |
| src/uipath_langchain/agent/react/output_files_node.py | Adds termination gate node that validates output file references and retries. |
| src/uipath_langchain/agent/react/llm_node.py | Factors max-iterations error creation into a shared helper. |
| src/uipath_langchain/agent/react/json_utils.py | Converts module into a backward-compatible re-export shim. |
| src/uipath_langchain/agent/react/job_attachments.py | Converts module into a backward-compatible re-export shim. |
| src/uipath_langchain/agent/react/conversational_output_node.py | Extracts a reusable conversational-output extractor callable. |
| src/uipath_langchain/agent/react/agent.py | Adds output-file verification node wiring and routing option. |
| src/uipath_langchain/agent/exceptions/exceptions.py | Adds max_iterations_error() helper. |
| src/uipath_langchain/agent/exceptions/init.py | Re-exports max_iterations_error. |
| src/uipath_langchain/agent/contracts/client_side_tools.py | Adds shared ClientSideToolInfo TypedDict contract. |
| src/uipath_langchain/agent/attachments/pydantic_json.py | Adds shared JSONPath + coercion helpers (moved from react/json_utils). |
| src/uipath_langchain/agent/attachments/output_files.py | Adds output-file discovery/prompting/verification logic and constants. |
| src/uipath_langchain/agent/attachments/job_attachments.py | Adds shared job-attachment utilities (moved from react/job_attachments). |
| src/uipath_langchain/agent/attachments/constants.py | Adds shared constant for the output-file tool name. |
| src/uipath_langchain/agent/advanced/utils.py | Enhances advanced utils: configurable state merging, message attachment hydration into workspace, shared attachments block rendering. |
| src/uipath_langchain/agent/advanced/types.py | Fixes defaults for message lists and adds alias validation config for conversational input base. |
| src/uipath_langchain/agent/advanced/code_interpreter.py | Adds optional QuickJS interpreter middleware factory with derived allowlist and replay-safety checks. |
| src/uipath_langchain/agent/advanced/agent.py | Adds payload handler middleware, max-iterations middleware, runtime system prompt resolution, output-file verification, conversation output extraction, and main-agent-only tool filtering. |
| src/uipath_langchain/agent/advanced/init.py | Exposes code-interpreter APIs and removes BackendFactory export. |
| src/uipath_langchain/_utils/durable_interrupt/decorator.py | Introduces SUSPENDS_RUN and suspends_run() helper. |
| src/uipath_langchain/_utils/durable_interrupt/init.py | Re-exports SUSPENDS_RUN and suspends_run. |
| src/uipath_langchain/_utils/_attachments.py | Adds shared, escaped rendering for <uip:attachments>...</uip:attachments> blocks. |
| samples/simple-deepagent/pyproject.toml | Pins deepagents version range used by sample. |
| samples/deepagent-storage-buckets/src/deepagent_storage_buckets/buckets_backend.py | Updates bucket backend to deepagents 0.7.x result types and helpers (ls/read/grep/glob signatures & payload shapes). |
| samples/deepagent-storage-buckets/pyproject.toml | Pins deepagents version range used by sample. |
| pyproject.toml | Bumps package version, updates core dependency versions, and adds code-interpreter extra. |
Suppressed comments (2)
src/uipath_langchain/agent/tools/internal_tools/output_file_tool.py:1
- The traversal check
\"..\" in virtual_pathis both too broad (rejects legitimate names like/report..md) and too narrow (it doesn’t reason about path segments). Consider validating using a POSIX path parser and rejecting if any path part is exactly'..'(and similarly handling backslashes if they’re possible inputs), before doing theresolve()+ containment check.
src/uipath_langchain/agent/tools/internal_tools/output_file_tool.py:1 - The MIME type
application/jsonlis not a commonly registered/standard type for JSON Lines; many ecosystems useapplication/x-ndjson(or sometimesapplication/json). If interoperability matters (downstream consumers relying on a standard MIME), consider switching.jsonltoapplication/x-ndjson.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| async def _download_missing( | ||
| paths: dict[uuid.UUID, Path], workspace: Path | ||
| ) -> dict[uuid.UUID, Path]: | ||
| """Fetch the attachments not already in the workspace, dropping those that fail.""" | ||
| missing = {key: path for key, path in paths.items() if not path.exists()} | ||
| if not missing: | ||
| return paths | ||
|
|
||
| logger.info("Downloading %d message attachment(s) into %s", len(missing), workspace) | ||
| client = UiPath() | ||
| outcomes = await asyncio.gather( | ||
| *( | ||
| client.attachments.download_async(key=key, destination_path=str(path)) | ||
| for key, path in missing.items() | ||
| ), | ||
| return_exceptions=True, | ||
| ) |
| def _with_file_paths( | ||
| attachments: list[dict[str, Any]], paths: dict[uuid.UUID, Path] | ||
| ) -> list[dict[str, Any]]: | ||
| resolved: list[dict[str, Any]] = [] | ||
| for attachment in attachments: | ||
| path = paths.get(uuid.UUID(str(attachment["id"]))) | ||
| if path is None: | ||
| resolved.append( | ||
| {key: value for key, value in attachment.items() if key != "file_path"} | ||
| ) | ||
| else: | ||
| resolved.append({**attachment, "file_path": f"/{path.name}"}) | ||
| return resolved |
| def get_output_file_fields(model: type[BaseModel]) -> list[OutputFileField]: | ||
| """Describe every job-attachment field declared by an output model. | ||
|
|
||
| Only top-level fields carry a name, description, and required flag that are | ||
| meaningful to state in a prompt; a nested attachment still gets a path so it | ||
| is verified, described by its path alone. | ||
| """ | ||
| by_json_key = { | ||
| field_info.alias or field_name: field_info | ||
| for field_name, field_info in model.model_fields.items() | ||
| } | ||
| fields = [] | ||
| for path in get_job_attachment_paths(model): | ||
| json_key = _json_key_from_path(path) | ||
| field_info = by_json_key.get(json_key) | ||
| fields.append( | ||
| OutputFileField( | ||
| path=path, | ||
| name=json_key, | ||
| description=(field_info.description or "") if field_info else "", | ||
| required=field_info.is_required() if field_info else False, | ||
| ) | ||
| ) | ||
| return fields |
|



Summary
Why
the uipath-agents release/s201 runtime stays on production rings 1 to 5 until s202 replaces it at the start of October, and it needs the advanced agent work from main without the unrelated changes that landed after this line was cut. cherry-picked from main in order: #1029, #1061, #1078, #1054, #1079, #1071, #1081. the 0.16.7.post2 MCP fix (#1095) stays in. skills support (#989) and the MCP tool metadata name (#1073) are left out on purpose, so one extra commit drops the skills parameter the picked commits assumed from #989. dependency floors are exactly the ones #1054 raised, everything else stays where 0.16.7.post2 had it, including the 1.17 langchain client line. hand resolutions: the react router keeps this line's thinking_messages_limit argument next to the new verify_output_files one, and llm_node keeps importing raise_for_provider_http_error from exceptions.licensing since #1067 is not on this line.