Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3238f50
feat(delegate): drive the public @uipath/delegate-stdio host
Mihaiii Sep 29, 2026
e533674
fix(delegate): record an interrupted tool as an error, not a success
Mihaiii Sep 29, 2026
7e23755
fix(delegate): categorize WAF blocks, SSE connect timeouts and sessio…
Mihaiii Sep 29, 2026
dc9c694
fix(delegate): keep the LLMGW_* secret out of agent shells when a tok…
Mihaiii Sep 29, 2026
780a4fb
feat(delegate)!: read the delegate-stdio host's own env var names; ro…
Mihaiii Sep 29, 2026
8359f4f
fix(delegate): keep the usage of the calls under a max_turns cut
Mihaiii Sep 30, 2026
c4f3554
fix(delegate): keep tool rows whose result has no open call
Mihaiii Oct 1, 2026
6a00727
fix(delegate): make crash retry independent of the stderr tail
Mihaiii Oct 1, 2026
9890cd9
feat(delegate)!: send auth to the host as an init option; read the DE…
Mihaiii Oct 1, 2026
4563218
docs(notes): shorten the Delegate agent section
Mihaiii Oct 1, 2026
0ea0d99
fix(delegate): record the SDK's LoadSkill call as the canonical Skill…
Mihaiii Oct 1, 2026
4292979
feat(delegate)!: find a global delegate-stdio install; rename DELEGAT…
Mihaiii Oct 3, 2026
4033863
chore(delegate): require @uipath/delegate-stdio 1.203.0
Mihaiii Oct 3, 2026
e4d64e5
fix(delegate): keep a non-retryable init error terminal on a respawn
Mihaiii Oct 3, 2026
03b00a8
fix(delegate): match an init 401/403 as a whole word
Mihaiii Oct 3, 2026
496f3e9
docs: say that the sdk_options keys and record depend on the agent type
Mihaiii Oct 3, 2026
a4cb6fd
docs(delegate): describe the host env scrub as defense in depth
Mihaiii Oct 3, 2026
669455d
test(golden): give the Delegate golden-coverage exemption a true reason
Mihaiii Oct 3, 2026
404b099
test(overrides): pin the sdk_options guard on the registry, not its c…
Mihaiii Oct 3, 2026
94e4a5a
fix(delegate): reject an sdk_options.effort that is not a string
Mihaiii Oct 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 106 additions & 88 deletions .claude/notes/agents.md

Large diffs are not rendered by default.

39 changes: 18 additions & 21 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -89,36 +89,33 @@ LOG_TO_FILE=false # Set to true to enable file logging
# CODER_EVAL_REMEDIATE_HOME_PLUGINS=0

# Delegate agent settings (UiPath Autopilot's Delegate agent, requires Node.js
# on PATH plus `npm install @uipath/delegate-sdk` — a genuinely public package,
# no token needed). See docs/agents/DELEGATE.md.
# on PATH plus `npm install -g @uipath/delegate-stdio`, a release that accepts the
# `auth` init option). coder_eval finds the install itself. See docs/agents/DELEGATE.md.
#
# DELEGATE_SDK_NODE_MODULES / DELEGATE_SDK_PATH — override the auto-located
# install (ancestor-walk from cwd, plus home); set at most one.
# DELEGATE_SDK_NODE_MODULES="/path/to/install/root"
# DELEGATE_SDK_PATH="/path/to/node_modules/@uipath/delegate-sdk/dist/index.mjs"
#
# DELEGATE_ENV — cloud environment slug (alpha/staging/production/localhost),
# used to derive the backend URL from the auth record's org/tenant slugs.
# DELEGATE_ENV — cloud environment slug (alpha/staging/production),
# used to derive the backend URL from the org/tenant slugs.
# DELEGATE_ENV="alpha"
#
# DELEGATE_BACKEND_URL — pin the full agent-service URL directly instead
# (wins over DELEGATE_ENV when both are set).
# DELEGATE_BACKEND_URL="https://cloud.uipath.com/<org>/<tenant>/delegate_"
#
# Auth: either the token set below, or a prior `delegate-sdk`/`delegate-cli`
# login that wrote ~/.aria/sdk-auth.json (read by the Node host itself, not
# by coder_eval). Each var also accepts a DELEGATE_-namespaced spelling
# (DELEGATE_AUTH_TOKEN, DELEGATE_TENANT_ID, ...), checked first -- prefer that
# spelling in a shared environment, since the bare names collide with what
# other tooling (npm, Vault, Terraform) commonly exports.
# AUTH_TOKEN="..."
# TENANT_ID="..."
# ORG_ID="..."
# Auth: either the token set below, or a prior `delegate-cli login`
# that wrote ~/.aria/sdk-auth.json (read by the Node host itself, not
# by coder_eval). coder_eval sends these values to the host as its `auth`
# init option, so the token stays out of the environment that the agent's
# shell tools inherit. Each var also accepts the bare spelling (AUTH_TOKEN,
# TENANT_ID, ORG_ID, ORG_SLUG, TENANT_SLUG) as a fallback -- prefer the
# DELEGATE_ spelling in a shared environment, since the bare names collide
# with what other tooling (npm, Vault, Terraform) commonly exports.
# DELEGATE_AUTH_TOKEN="..."
# DELEGATE_TENANT_ID="..."
# DELEGATE_ORG_ID="..."
# With DELEGATE_ENV (not DELEGATE_BACKEND_URL) also set these two -- the
# human-readable org/tenant names, not the GUIDs above -- or init fails with
# "--env alpha needs org/tenant slugs". See docs/agents/DELEGATE.md.
# ORG_SLUG="..."
# TENANT_SLUG="..."
# 'env="alpha" requires org/tenant slugs'. See docs/agents/DELEGATE.md.
# DELEGATE_ORG_SLUG="..."
# DELEGATE_TENANT_SLUG="..."

# Usage Telemetry (anonymous; on by default).
# Disable entirely:
Expand Down
43 changes: 20 additions & 23 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1175,8 +1175,8 @@ jobs:
retention-days: 7

delegate-live-tests:
# Live Delegate e2e: spawns the real Node host (agents/delegate/delegate_host.mjs)
# wrapping the public @uipath/delegate-sdk against a real UiPath backend. Runs on
# Live Delegate e2e: spawns the real Node host from the public
# @uipath/delegate-stdio package against a real UiPath backend. Runs on
# every PR/push like the other live-test jobs (codex-live-tests, byoa-live-tests)
# now that the DELEGATE_ROPC_* secrets are provisioned; the presence-check gate
# below skips cleanly ONLY on a fork PR (no secrets available there) and fails
Expand All @@ -1187,10 +1187,10 @@ jobs:
# and implemented in coder_eval_uipath/eval_runner/scripts/ci/refresh-auth.sh —
# rather than a long-lived AUTH_TOKEN secret, since a minted token's ~1h TTL
# would make a static secret stale between runs. A dedicated bot user's
# username/password is the durable credential; the Delegate SDK reads the
# minted token straight from AUTH_TOKEN/TENANT_ID/ORG_ID (see
# docs/agents/DELEGATE.md), so no sdk-auth.json or client-secret refresh chain
# is needed here.
# username/password is the durable credential; the agent sends the minted
# token (DELEGATE_AUTH_TOKEN, with DELEGATE_TENANT_ID / DELEGATE_ORG_ID) to the
# host as its `auth` init option (see docs/agents/DELEGATE.md), so no
# sdk-auth.json or client-secret refresh chain is needed here.
name: Delegate Live E2E (ROPC)
runs-on: uipath-ubuntu-24.04
timeout-minutes: 15
Expand Down Expand Up @@ -1260,7 +1260,7 @@ jobs:
if: steps.gate.outputs.present == 'true'
run: uv sync --frozen --extra dev

- name: Install @uipath/delegate-sdk (public npm, no token needed)
- name: Install @uipath/delegate-stdio (public npm, no token needed)
if: steps.gate.outputs.present == 'true'
working-directory: src/coder_eval/agents/delegate
# --safe-chain-skip-minimum-package-age (not a growing exclusion-list entry
Expand Down Expand Up @@ -1372,17 +1372,15 @@ jobs:
- name: Run fizzbuzz delegate task (assert PASS)
if: steps.gate.outputs.present == 'true'
env:
DELEGATE_SDK_NODE_MODULES: ${{ github.workspace }}/src/coder_eval/agents/delegate
DELEGATE_ENV: ${{ github.event.inputs.delegate_uipath_env || 'alpha' }}
AUTH_TOKEN: ${{ steps.ropc.outputs.access_token }}
TENANT_ID: ${{ secrets.DELEGATE_TENANT_ID }}
ORG_ID: ${{ secrets.DELEGATE_ORG_ID }}
# Forwarded into `auth.organizationName` / `auth.tenantName` by
# DelegateAgent._build_init_options (see .claude/notes/agents.md §
# Delegate agent) — needed alongside the GUIDs above whenever
# `environment` (rather than `backendUrl`) resolves the backend.
ORG_SLUG: ${{ secrets.DELEGATE_ORG_SLUG }}
TENANT_SLUG: ${{ secrets.DELEGATE_TENANT_SLUG }}
DELEGATE_AUTH_TOKEN: ${{ steps.ropc.outputs.access_token }}
DELEGATE_TENANT_ID: ${{ secrets.DELEGATE_TENANT_ID }}
DELEGATE_ORG_ID: ${{ secrets.DELEGATE_ORG_ID }}
# Needed alongside the GUIDs above whenever DELEGATE_ENV (rather than
# DELEGATE_BACKEND_URL) resolves the backend; the agent sends all five to
# the host as its `auth` init option (see .claude/notes/agents.md § Delegate agent).
DELEGATE_ORG_SLUG: ${{ secrets.DELEGATE_ORG_SLUG }}
DELEGATE_TENANT_SLUG: ${{ secrets.DELEGATE_TENANT_SLUG }}
run: .venv/bin/coder-eval run tasks/delegate/fizzbuzz_delegate.yaml --run-dir runs/delegate-live

- name: Verify Delegate live run PASSED
Expand All @@ -1405,13 +1403,12 @@ jobs:
- name: Run Delegate live unit tests (assert PASS)
if: steps.gate.outputs.present == 'true'
env:
DELEGATE_SDK_NODE_MODULES: ${{ github.workspace }}/src/coder_eval/agents/delegate
DELEGATE_ENV: ${{ github.event.inputs.delegate_uipath_env || 'alpha' }}
AUTH_TOKEN: ${{ steps.ropc.outputs.access_token }}
TENANT_ID: ${{ secrets.DELEGATE_TENANT_ID }}
ORG_ID: ${{ secrets.DELEGATE_ORG_ID }}
ORG_SLUG: ${{ secrets.DELEGATE_ORG_SLUG }}
TENANT_SLUG: ${{ secrets.DELEGATE_TENANT_SLUG }}
DELEGATE_AUTH_TOKEN: ${{ steps.ropc.outputs.access_token }}
DELEGATE_TENANT_ID: ${{ secrets.DELEGATE_TENANT_ID }}
DELEGATE_ORG_ID: ${{ secrets.DELEGATE_ORG_ID }}
DELEGATE_ORG_SLUG: ${{ secrets.DELEGATE_ORG_SLUG }}
DELEGATE_TENANT_SLUG: ${{ secrets.DELEGATE_TENANT_SLUG }}
run: |
mkdir -p tmp
.venv/bin/pytest tests/test_delegate_agent_live.py \
Expand Down
6 changes: 4 additions & 2 deletions docs/REPORT_SCHEMA.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,10 @@ The authoritative per-replicate record.
**Errors** (populated on failure): `error_message`, `error_details`,
`error_log_tail` (carries the Docker build-log tail for `BUILD_FAILED`).

**Config/environment:** `environment_info`, `agent_config`, `sdk_options` (raw
`ClaudeAgentOptions` dump), `sandbox_path`, `task_config`
**Config/environment:** `environment_info`, `agent_config`, `sdk_options` (the
options the agent sent to its SDK; the shape depends on the agent: a raw
`ClaudeAgentOptions` dump on Claude Code, the host's `init` options with
credentials redacted on Delegate, `null` on the other agents), `sandbox_path`, `task_config`
(`{resolved, source_yaml, source_file, lineage}` — `lineage` maps each field to
`{value, source, source_detail}` so you can trace which config layer set it).
`environment_info.system_prompt_semantics` (`"append"` / `"replace"` /
Expand Down
25 changes: 15 additions & 10 deletions docs/TASK_DEFINITION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,18 +170,23 @@ agent:
- "Write"
- "Bash"
model: "claude-sonnet-5" # Optional: specific model
sdk_options: # Optional: Claude Code SDK pass-through
effort: high # any non-framework-managed ClaudeAgentOptions field
sdk_options: # Optional: agent SDK pass-through (keys depend on `type`)
effort: high # claude-code: any non-framework-managed ClaudeAgentOptions field
```

**`sdk_options`** is a typed pass-through dict for Claude Code SDK
`ClaudeAgentOptions` fields that Coder Eval doesn't own directly. Keys are
validated against the SDK's dataclass at YAML load; framework-managed keys
(`model`, `allowed_tools`, `permission_mode`, `hooks`, `mcp_servers`, …)
are rejected. Deep-merged across the 5-layer config chain. Override via
CLI with the repeatable `-D agent.sdk_options.KEY=VALUE`.
**Requires `type: "claude-code"`** to function; on other agent types it raises
an error.
**`sdk_options`** is a pass-through dict for the agent SDK options that Coder
Eval doesn't own directly. Only an agent type whose config declares the field
accepts it; on another agent type it raises an error. Each agent type
validates its own keys at YAML load:

- `claude-code` — `ClaudeAgentOptions` fields, validated against the SDK's
dataclass; framework-managed keys (`model`, `allowed_tools`,
`permission_mode`, `hooks`, `mcp_servers`, …) are rejected. See the
[Claude Code guide](agents/CLAUDE_CODE.md).
- `delegate` — only `effort`. See the [Delegate guide](agents/DELEGATE.md).

Deep-merged across the 5-layer config chain. Override via CLI with the
repeatable `-D agent.sdk_options.KEY=VALUE`.

**Permission Modes:**
- `default` — Default permission handling
Expand Down
2 changes: 1 addition & 1 deletion docs/USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ Set these in `.env` (copy from `.env.example`).
| `BEDROCK_SMALL_MODEL` | No | Cross-region Bedrock small/fast model ID |
| `CODEX_API_KEY` / `CODEX_BASE_URL` / `CODEX_MODEL` / `CODEX_API_VERSION` | For Codex | Codex agent auth & endpoint routing — see [Codex Agent Guide](agents/CODEX.md#endpoint-routing). |
| `GEMINI_API_KEY` / `ANTIGRAVITY_MODEL` | For Antigravity | Antigravity (Gemini) agent auth & model — see [Antigravity Agent Guide](agents/ANTIGRAVITY.md#setup). |
| `DELEGATE_ENV` / `DELEGATE_BACKEND_URL` / `AUTH_TOKEN` / `TENANT_ID` / `ORG_ID` / `ORG_SLUG` / `TENANT_SLUG` / `DELEGATE_SDK_NODE_MODULES` / `DELEGATE_SDK_PATH` | For Delegate | Delegate agent backend routing, auth & SDK install location — see [Delegate Agent Guide](agents/DELEGATE.md#setup). |
| `DELEGATE_ENV` / `DELEGATE_BACKEND_URL` / `DELEGATE_AUTH_TOKEN` / `DELEGATE_TENANT_ID` / `DELEGATE_ORG_ID` / `DELEGATE_ORG_SLUG` / `DELEGATE_TENANT_SLUG` | For Delegate | Delegate agent backend routing & auth — see [Delegate Agent Guide](agents/DELEGATE.md#setup). |
| `UIPATH_PLUGIN_MARKETPLACE_DIR` | No | Conventional base directory for local plugins. Not special-cased by the framework: **any** `$VAR` / `${VAR}` referenced in a plugin `path` is expanded from the environment, so a plugin path like `$UIPATH_PLUGIN_MARKETPLACE_DIR/my-plugin` resolves against this variable. (An undefined variable in a plugin path logs a warning.) |
| `PLUGIN_TOOLS_DIR` | No | A *separate* mechanism from the above: the canonical `node_modules/@uipath` directory used to pin UiPath CLI plugin discovery (not path substitution). When unset, the sandbox auto-derives it from the resolved `uip` binary. |
| `CODER_EVAL_REMEDIATE_HOME_PLUGINS` | No | **DESTRUCTIVE.** Truthy deletes `$HOME/node_modules/@uipath` at sandbox setup to clear sibling-task pollution on dedicated eval hosts. Off by default; do **not** enable on developer workstations. |
Expand Down
Loading
Loading