Skip to content

feat: HitlSchema types and dynamic QuickForm dispatch for guardrail escalations#1737

Draft
dushyant-uipath wants to merge 2 commits into
mainfrom
feat/guardrail-dynamic-hitl-schema
Draft

feat: HitlSchema types and dynamic QuickForm dispatch for guardrail escalations#1737
dushyant-uipath wants to merge 2 commits into
mainfrom
feat/guardrail-dynamic-hitl-schema

Conversation

@dushyant-uipath

Copy link
Copy Markdown
Contributor

Summary

  • Adds uipath-platform/hitl/ module with HitlSchema, HitlSchemaField, HitlSchemaOutcome, HitlFieldType, HitlFieldDirection — Python mirror of @uipath/hitl-schema-types
  • Adds pydantic_to_hitl_schema(): converts Pydantic models to HitlSchema; field aliases become schema field IDs
  • Adds hitl_schema: HitlSchema | None field to CreateTask / CreateEscalation
  • _handle_task_trigger dispatches to create_quickform_async when hitl_schema is set — no pre-deployed Action App required
  • Deterministic taskSchemaKey derived from SHA-256 of schema content (Orchestrator upserts, no duplicates)

Context

Part of the dynamic schemas feature for agent guardrail escalations. Instead of requiring a developer to pre-deploy a static Action App with fixed form fields, the schema is generated at runtime by the LLM and travels inline with the escalation interrupt.

This PR is the platform foundation. The LangChain runtime PR (uipath-langchain-python) depends on this being published first.

See design doc: https://uipath.atlassian.net/wiki/spaces/BPA/pages/90813301792/Dynamic+Schemas+for+Agent+Guardrail+Escalations

Test plan

  • uv run pytest packages/uipath-platform/tests/services/test_hitl_schema.py — 20 new unit tests
  • Full platform suite: uv run pytest packages/uipath-platform/tests/

🤖 Generated with Claude Code


INPUT = "input"
OUTPUT = "output"
IN_OUT = "inOut"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we have this case?
Generarly at pre target execution, the input field is editable.
At post target execution, we show both fields (input and output), but only output is editable. Doesn't make sense to edit input since it is allready consumed by llm/tool.

…tasks

Adds a new `hitl/` module to `uipath-platform` with `HitlSchema`,
`HitlSchemaField`, `HitlSchemaOutcome`, `HitlFieldType`, and
`HitlFieldDirection` — a Python mirror of `@uipath/hitl-schema-types`.

`pydantic_to_hitl_schema()` converts Pydantic models into `HitlSchema`
instances. Field aliases become the schema field IDs, enabling PascalCase
form field names while keeping Python field names snake_case.

`CreateTask` gains an optional `hitl_schema` field. When set,
`_handle_task_trigger` routes to `create_quickform_async` instead of
`create_async`, sending the schema inline to `GenericTasks/CreateTask`
(type=6). A deterministic UUID derived from the schema content is used
as `taskSchemaKey` so Orchestrator can upsert rather than duplicate.

No pre-deployed Action App is required when a schema is provided.
…ma mode

When an agent guardrail is configured for dynamic schema generation (no
pre-deployed Action App), the JSON config has no `app` field.  Making
`app` Optional allows this config to deserialize without error — the
factory then creates EscalateAction with model-injected schema generation.
@dushyant-uipath
dushyant-uipath force-pushed the feat/guardrail-dynamic-hitl-schema branch from cfc5b8e to 86e52db Compare July 16, 2026 19:27
dushyant-uipath added a commit to UiPath/uipath-langchain-python that referenced this pull request Jul 16, 2026
…alations

When a guardrail fires and triggers an escalation, the agent's own LLM
now generates a HitlSchema from the full conversation context —
system prompt, user request, and the offending tool call — using
`model.with_structured_output(HitlSchema)`.

The generated schema travels inline with the QuickForm task request
(via `create_quickform_async`). No pre-deployed Action App is required.

Implementation:
- `EscalateAction` (agent graph path) gains an optional `model` field.
  When set, schema is generated dynamically; when absent, falls back to
  the existing static Action App path for backward compatibility.
- `create_agent` injects the model into any `EscalateAction` in the
  guardrails list before wiring subgraphs — no API change for callers.
- Middleware `EscalateAction` is unchanged (no state.messages access).

Depends on: UiPath/uipath-python#1737 (HitlSchema types + QuickForm dispatch)
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
85.7% Coverage on New Code (required ≥ 90%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:uipath-integrations test:uipath-langchain Triggers tests in the uipath-langchain-python repository

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants