Skip to content

Windows: workflow agent handoff rejects successful result artifacts due to path separators #284

Description

@yxr-2025

Problem

On Windows, a workflow child agent can complete successfully and persist the correct structured result, but the DSL agent() call receives ok: false with:

Workflow handoff result artifact is invalid

This breaks successful schema-based workflow agents on Windows: the child execution and audit artifact are correct, but the handoff fails, no result ref is produced, and downstream inputs: chains are interrupted.

Environment

  • OS: Windows
  • OpenPI: current upstream main at a15a0d8
  • Node.js: v24.12.0

Reproduction

node --test --experimental-strip-types --test-name-pattern "agent calls run through the injected session factory" tests/extensions/workflows/execute.e2e.test.ts

The test deterministically fails in about 2.6 seconds. The workflow reports the child agent as successful, but its DSL result is:

{
  "ok": false,
  "output": ""
}

A direct boundary probe shows the mismatch:

artifact=agent-results\agent-0001.json
handoff=Workflow handoff result artifact is invalid

Root cause

persistWorkflowAgentResult() creates a persisted protocol identity with the platform-dependent path.join():

https://github.com/openpi-dev/openpi/blob/a15a0d8/extensions/workflows/artifacts.ts#L130-L133

On Windows this returns:

agent-results\agent-0001.json

The handoff registry correctly accepts only the canonical POSIX grammar:

https://github.com/openpi-dev/openpi/blob/a15a0d8/extensions/workflows/handoff.ts#L190-L197

agent-results/agent-0001.json

The dashboard projection also assumes the canonical / prefix:

https://github.com/openpi-dev/openpi/blob/a15a0d8/extensions/workflows/dashboard.ts#L352-L355

The current artifact unit test verifies that the returned value can be used as a local filesystem path, but does not assert that the persisted artifact identity is platform-independent.

Expected behavior

Persisted workflow artifact identities should always use canonical POSIX / separators on every host. Filesystem access can continue resolving that run-relative identity with the platform path APIs.

A successful child agent with structured output should remain ok: true, produce a handoff ref, and remain usable by downstream workflow inputs on Windows.

Suggested fix

Generate the identity with a POSIX join or an explicit canonical join at the producer boundary, for example:

const artifact = path.posix.join(
  "agent-results",
  `agent-${String(index).padStart(4, "0")}.json`,
);

Prefer keeping the consumer strict instead of accepting both slash formats, so persisted artifact identities remain canonical.

Regression coverage

  • Assert persistWorkflowAgentResult() returns agent-results/agent-0001.json on Windows and other platforms.
  • Keep the existing execute E2E green on Windows and verify the successful DSL result includes the expected output/ref.
  • Verify the persisted workflow.json uses / in resultArtifact.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions