Skip to content

feat: let agents produce output files as job attachments - #1061

Merged
radu-mocanu merged 2 commits into
mainfrom
feat/agent-output-files
Sep 7, 2026
Merged

feat: let agents produce output files as job attachments#1061
radu-mocanu merged 2 commits into
mainfrom
feat/agent-output-files

Conversation

@radu-mocanu

@radu-mocanu radu-mocanu commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • an agent whose output schema declares a file field now gets a create_output_file tool that publishes its content as a job attachment and returns the reference to put in that field
  • works for standard and advanced agents; advanced agents can publish a file already written to their workspace by path, so the body never round-trips through the model
  • the format follows the field's description, and the agent picks one that fits the content when the description names none
  • a required file field left empty, or a reference to an attachment not linked to the job, sends the agent back for another turn rather than emitting an output it cannot honor
  • conversational advanced agents can now declare output fields, filled by the same post-loop extraction call standard conversational agents use

Why

files were input-only. the output schema could declare a file, and the product even nudged you toward it, but nothing could produce one: the agent had no way to create an attachment and the termination path only validated whatever the model claimed, so the field was unfillable.

Advanced agent with file output

image

Standard agent with file output

image

Copilot AI lite review requested due to automatic review settings September 1, 2026 15:30

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds first-class support for agent-produced output files by introducing an internal create_output_file tool (returning a job-attachment ticket) and adding pre-termination verification that required file outputs are present and linked to the current job. This extends the agent orchestration layer to safely support output schemas that include job-attachment fields, including advanced-agent and conversational-advanced flows.

Changes:

  • Introduce create_output_file internal tool and shared JOB_ATTACHMENT_DEFINITION schema for job-attachment fields.
  • Add output-file field discovery + verification (including retry gating) and wire a new VERIFY_OUTPUT_FILES node into the ReAct and advanced-agent graphs.
  • Refactor conversational structured-output extraction into a reusable extractor and enable conversational advanced agents to declare additional output fields.
File summaries
File Description
uv.lock Updates lock metadata and bumps package version to 0.16.14.
pyproject.toml Bumps project version to 0.16.14.
src/uipath_langchain/agent/tools/internal_tools/schema_utils.py Extracts reusable JOB_ATTACHMENT_DEFINITION for job-attachment schemas.
src/uipath_langchain/agent/tools/internal_tools/output_file_tool.py Adds the create_output_file internal tool to publish job attachments.
src/uipath_langchain/agent/attachments/output_files.py Adds output-file field discovery, prompt builder, and attachment-link verification helpers.
src/uipath_langchain/agent/react/types.py Adds output-file verification state fields and a new graph node enum value.
src/uipath_langchain/agent/react/router.py Routes end_execution through output-file verification when enabled.
src/uipath_langchain/agent/react/output_files_node.py Adds a verification gate node that can bounce control back to the agent with corrective feedback.
src/uipath_langchain/agent/react/conversational_output_node.py Refactors conversational extraction into create_conversational_output_extractor() and rewraps it as a node.
src/uipath_langchain/agent/react/agent.py Wires the verification node into the standard ReAct graph when file outputs are expected.
src/uipath_langchain/agent/advanced/agent.py Adds output-file verification to advanced agents and output-field extraction for conversational advanced agents.
tests/agent/tools/internal_tools/test_output_file_tool.py Adds unit tests for tool schema, MIME guessing, and attachment creation behavior.
tests/agent/attachments/test_output_files.py Adds tests for output-file field discovery, prompt text, and verification logic.
tests/agent/react/test_output_files_node.py Adds tests for verification node behavior and graph wiring.
tests/agent/advanced/test_create_advanced_agent_graph.py Adds tests asserting verification node/state wiring in advanced agent graphs.
tests/agent/advanced/test_conversational_advanced_agent_graph.py Adds tests for conversational output extraction node insertion and output merging.
Review details
  • Files reviewed: 15/16 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/uipath_langchain/agent/tools/internal_tools/output_file_tool.py Outdated
Comment thread src/uipath_langchain/agent/attachments/output_files.py Outdated
@radu-mocanu
radu-mocanu force-pushed the feat/agent-output-files branch 12 times, most recently from 57a0a8b to 9e14466 Compare September 7, 2026 14:54
An output schema could declare a file field, but nothing could fill it: the
agent had no way to create an attachment, and the termination path only
validated whatever the model claimed.

Add a create_output_file tool that publishes agent-authored content as a job
attachment and returns the attachment ticket, plus a verification gate that
runs just before termination. The gate routes with Command, sending the agent
back with a corrective message and faulting only once the retries are spent.
Reaching it without an end_execution call raises rather than passing the output
through, since the router is the only route in and letting it past would skip
verification silently.

Whether to verify is the caller's decision, carried by output_files_enabled
rather than inferred from the tools present: a process tool or coded function
can return a real ticket too, so an agent without create_output_file still
needs its output checked.

The gate has to catch everything the output schema would reject, or termination
hard-fails on validation and the agent never gets its corrective turn. Three
ways that could happen, each covered:

- A field is matched by its JSON key, which is the alias when the converter
  assigned one. A property named `schema` becomes `schema_` with that alias, so
  matching model-field names alone silently made it optional.
- A filled field is shape-checked against Attachment itself rather than by
  hand, so a half-filled reference (an id with no name) is corrected rather
  than faulted.
- A complete reference is checked against the attachments linked to this job,
  so an invented id cannot pass.

An optional file field is offered but never demanded: the prompt states the
obligation per declared kind, and only a required field left empty counts as
missing. A field the agent does fill is verified either way.

The tool takes inline content everywhere, and a workspace path as well when the
backend exposes a root, so an advanced agent does not re-emit a file body
through the model. Paths resolve against deepagents' public `cwd`, the same seam
the input-attachment path writes through, with traversal and containment checked
here rather than delegated to a private resolver whose disappearance would
silently drop the argument.

The tool's output schema reuses single_attachment_schema, which batch transform
already needed for the same shape.
A conversational agent's loop produces messages, so nothing in it fills the
fields its output schema declares. The standard path already solves this with a
focused extraction call after the loop, forced onto the set_conversational_output
tool. The advanced path had no equivalent and returned messages only.

Split that extraction out of the react node into
create_conversational_output_extractor, which is graph agnostic, and build a
node over it in the conversational advanced wrapper graph. The react node keeps
its behavior and now delegates.

The extraction receives the whole transcript, as the standard path passes: a
declared field's answer often lives in the user's message or an earlier
exchange, not in what the agent just produced.
@radu-mocanu
radu-mocanu force-pushed the feat/agent-output-files branch from 9e14466 to 124f05d Compare September 7, 2026 15:05
@sonarqubecloud

sonarqubecloud Bot commented Sep 7, 2026

Copy link
Copy Markdown

@radu-mocanu
radu-mocanu merged commit 5331f6e into main Sep 7, 2026
77 of 78 checks passed
@radu-mocanu
radu-mocanu deleted the feat/agent-output-files branch September 7, 2026 15:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants