Skip to content

feat(action-center): extend taskSourceMetadata on CreateTask/CreateEscalation - #1873

Open
dushyant-uipath wants to merge 1 commit into
mainfrom
conversational-agent-task-source-metadata
Open

feat(action-center): extend taskSourceMetadata on CreateTask/CreateEscalation#1873
dushyant-uipath wants to merge 1 commit into
mainfrom
conversational-agent-task-source-metadata

Conversation

@dushyant-uipath

@dushyant-uipath dushyant-uipath commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Problem

taskSource.taskSourceMetadata is assembled inside _apply_task_source (action_center/_tasks_service.py) from UiPathConfig state: InstanceId, FolderKey, JobKey, ProcessKey. CreateTask's other fields (data, actionable_message_metadata, labels, etc.) each map onto a parameter of _create_spec. taskSourceMetadata does not, since it is built entirely from UiPathConfig rather than from a CreateTask field.

Decision

Add an optional task_source_metadata: dict[str, Any] | None field to CreateTask (inherited by CreateEscalation), merged into taskSourceMetadata on top of the built-in keys. Caller keys win on collision.

Usecase

Any caller of CreateTask/CreateEscalation can attach arbitrary key/value context to taskSource.taskSourceMetadata, the same block that already carries job/process correlation ids (InstanceId, FolderKey, JobKey, ProcessKey). Anything reading the task record downstream, Orchestrator, Plugins, or another resume-trigger consumer, gets that context alongside the built-in keys.

The concrete case behind this (ACTN-123): Verticals' Purchase Request solution routes HITL reviews through a unified Teams interface, where a reviewer can ask questions to a conversational agent tied to that task. The escalation is created by a coded agent (decision-router), via interrupt(CreateEscalation(...)), as an inner step of the BPMN's decision-router node, rather than through a dedicated HITL node with its own resource picker. That puts the conversational-agent choice for a given step in the coded agent itself, not in Studio Web. The interim fix hardcodes a conversationalAgentId in decision-router and passes it on the task, so the Plugins service can read it off taskSourceMetadata and attach the right conversational agent to the actionable card.

sequenceDiagram
    participant Agent as decision-router (coded agent)
    participant Trig as UiPathResumeTriggerCreator
    participant Tasks as TasksService.create_async
    participant Orch as Orchestrator (CreateAppTask)
    participant Plugins as Plugins service

    Agent->>Agent: interrupt(CreateEscalation(task_source_metadata={"ConversationalAgentId": id}))
    Agent->>Trig: job suspends on the CreateEscalation value
    Trig->>Tasks: create_async(..., task_source_metadata=value.task_source_metadata)
    Tasks->>Orch: POST taskSource.taskSourceMetadata = {InstanceId, FolderKey, JobKey, ProcessKey, ConversationalAgentId}
    Orch-->>Plugins: task record carries taskSource.taskSourceMetadata
    Plugins->>Plugins: reads ConversationalAgentId, attaches the conversational agent to the actionable card
Loading

This is a draft for the platform team's review; open to folding task_source_metadata into actionable_message_metadata instead, if that fits the wire contract better.

Changes

  • common/interrupt_models.py: new task_source_metadata field on CreateTask.
  • resume_triggers/_protocol.py: _handle_task_trigger passes value.task_source_metadata into the tasks.create_async(...) call it makes when a job suspends on CreateTask/CreateEscalation. Without this, a value set on the interrupt object would never reach the API call.
  • action_center/_tasks_service.py: TasksService.create/create_async accept task_source_metadata, pass it to _create_spec, which passes it to _apply_task_source, where it merges into taskSourceMetadata.

Compatibility

New parameter, defaults to None. Pydantic's generated __init__ for CreateTask takes **data, so its fields are keyword-only; create/create_async already require keyword arguments past data. Existing callers of CreateTask, CreateEscalation, TasksService.create, and TasksService.create_async see no behavior change unless they start passing task_source_metadata themselves.

Test plan

  • Added test_create_merges_task_source_metadata, test_create_async_merges_task_source_metadata, test_create_omits_extra_task_source_metadata_when_unset in packages/uipath-platform/tests/services/test_actions_service.py.
  • Full suite not run locally. CI runs pytest across packages/uipath-platform, including the three new tests above.

@github-actions github-actions Bot added test:uipath-langchain Triggers tests in the uipath-langchain-python repository test:uipath-integrations labels Aug 27, 2026
@dushyant-uipath
dushyant-uipath force-pushed the conversational-agent-task-source-metadata branch 3 times, most recently from c3aa950 to a400801 Compare September 3, 2026 08:16
@dushyant-uipath
dushyant-uipath marked this pull request as ready for review September 3, 2026 08:29
Copilot AI lite review requested due to automatic review settings September 3, 2026 08:29
…sk/CreateEscalation

HITL tasks created via interrupt(CreateEscalation(...)) have no way to carry
caller-supplied context (e.g. a conversational-agent id) in taskSource.taskSourceMetadata
today; it is built entirely from UiPathConfig state with no extension point.

Add an optional task_source_metadata dict to CreateTask (inherited by CreateEscalation)
and TasksService.create/create_async, threaded through _create_spec and merged into
taskSourceMetadata (as custom_metadata) on top of the built-in
InstanceId/FolderKey/JobKey/ProcessKey keys. Additive only; no change for existing callers.
@dushyant-uipath
dushyant-uipath force-pushed the conversational-agent-task-source-metadata branch 2 times, most recently from a400801 to 48b2250 Compare September 3, 2026 08:31

Copilot AI left a comment

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.

🟡 Changes recommended

A few small but user-facing issues remain (metadata merge can raise an opaque TypeError on invalid keys, collision behavior isn’t asserted, and docs should clarify when taskSource is populated).

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

Pull request overview

Extends the Action Center task creation surface so callers of CreateTask / CreateEscalation (including resume-trigger flows) can attach arbitrary additional key/value context into taskSource.taskSourceMetadata, merged on top of the SDK’s built-in correlation keys.

Changes:

  • Added task_source_metadata to the CreateTask interrupt model and threaded it through resume triggers into TasksService.create/create_async.
  • Extended task request spec building to merge caller-provided metadata into taskSource.taskSourceMetadata (caller wins on collision).
  • Added tests to validate metadata merging behavior and bumped uipath-platform version.
File summaries
File Description
packages/uipath-platform/src/uipath/platform/common/interrupt_models.py Adds task_source_metadata to CreateTask (inherited by CreateEscalation).
packages/uipath-platform/src/uipath/platform/resume_triggers/_protocol.py Passes interrupt-provided task_source_metadata into tasks.create_async(...).
packages/uipath-platform/src/uipath/platform/action_center/_tasks_service.py Plumbs task_source_metadata through create/create_async into request payload taskSourceMetadata.
packages/uipath-platform/tests/services/test_actions_service.py Adds tests covering merge/omit behavior for extra task-source metadata.
packages/uipath-platform/tests/services/test_hitl.py Updates interrupt construction to include the new field in the test setup.
packages/uipath-platform/pyproject.toml Bumps package version to 0.2.24.
packages/uipath-platform/uv.lock Updates lockfile version entry for uipath-platform.
Review details

Suppressed comments (1)

packages/uipath-platform/src/uipath/platform/action_center/_tasks_service.py:627

  • Same as create_async: task_source_metadata is ignored unless _apply_task_source populates the taskSource block (requires UiPathConfig.project_id and UiPathConfig.trace_id). Adding that note here would prevent confusion for callers.
            task_source_metadata: Optional extra keys merged into taskSource.taskSourceMetadata,
                on top of the built-in InstanceId/FolderKey/JobKey/ProcessKey (e.g. a
                conversational-agent id a HITL task should carry downstream)
  • Files reviewed: 6/8 changed files
  • Comments generated: 3
  • 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 on lines 217 to +221
"InstanceId": trace_id,
"FolderKey": UiPathConfig.folder_key,
"JobKey": UiPathConfig.job_key,
"ProcessKey": UiPathConfig.process_uuid,
**(custom_metadata or {}),
Comment on lines +526 to +528
task_source_metadata: Optional extra keys merged into taskSource.taskSourceMetadata,
on top of the built-in InstanceId/FolderKey/JobKey/ProcessKey (e.g. a
conversational-agent id a HITL task should carry downstream)
Comment on lines +1037 to +1050
service.create(
title="Test Action",
app_key="test-app-key",
data={"test": "data"},
task_source_metadata={"ConversationalAgentId": "agent-1"},
)

task_source_metadata = _posted_body(httpx_mock, create_task_url)["taskSource"][
"taskSourceMetadata"
]
assert task_source_metadata["ConversationalAgentId"] == "agent-1"
# The built-in correlation keys are still populated alongside the extra one.
assert task_source_metadata["InstanceId"] == "trace-1"

@sonarqubecloud

sonarqubecloud Bot commented Sep 3, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

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