Skip to content

Attribute Pi main/sub-agent requests with x-awf-caller and preserve caller metadata - #71043

Draft
SivaKesava1 with Copilot wants to merge 7 commits into
mainfrom
copilot/attribute-caller-metadata
Draft

SivaKesava1 with Copilot wants to merge 7 commits into
mainfrom
copilot/attribute-caller-metadata

Conversation

Copilot AI commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

gh-aw never sent AWF's x-awf-caller header. Proxy accounting records therefore had no explicit main/sub-agent identity, and the collector also dropped AWF's agent_name / caller_source fields. This PR sends the header where a harness has a real per-caller boundary (currently only Pi), keeps the caller fields in the unified session, and makes audit/logs prefer them over token/model/time correlation.

Harnesses

  • Pi: pi_provider.cjs sets the header in every Pi process's before_provider_headers hook.
    • The parent process (CLI, SDK/agent-core and RPC paths) sends main.
    • Each sub-agent process launched by pi_subagent_extension.cjs sends subagent/<name>. The name is passed in that process's environment as GH_AW_PI_SUBAGENT_NAME.
    • Values are checked against ^(?:main|subagent/[A-Za-z0-9_.:/-]+)$ and the 128-character limit. An invalid value means no header is sent; names are never truncated.
    • API selection and models.json are unchanged.
  • Copilot SDK 1.0.16, Copilot CLI, Claude Code, Codex 0.163.0: no header is sent. Their header mechanisms apply to a whole provider or process, so a main header would also land on sub-agent requests.
    • For the Copilot SDK, giving each declared agent its own provider entry would change the qualified model IDs that model resolution and audit depend on.
    • These requests stay unattributed. The spec's engine table records the limitation for each engine.

Collector and contract

  • firewall.token_usage and usage.report now project:
    • agent_name / agentName → agentName
    • caller_source / callerSource → callerSource
  • purpose was already projected and is unchanged. AWF's classifier records now also keep callerSource: awf.
  • Absent fields stay absent and nothing is synthesized.
  • Updated unified_session.d.ts and regenerated unified-session.schema.json.
  • Unified session spec bumped to 2.4.0: new requirement T-UAS-083, a per-engine support table, a compliance-matrix row and a changelog entry.

Audit and logs (pkg/cli)

  • TokenUsageEntry carries agent_name and caller_source. They are read from the unified session and, when the session has no token-usage events, from raw token-usage.jsonl.
  • Records with an explicit caller are attributed first:
    • Credits go to the named Pi sub-agent row, and those records are reserved.
    • Records naming an unknown agent produce a warning and are not credited.
    • Explicit main records are counted as main and never inferred as children.
  • Correlation now only covers what explicit attribution left over: sub-agents with no explicit records, matched against unlabelled records only. Older records without caller fields keep today's behaviour. A missing purpose stays unknown.
  • AWF-owned records (routing_classification or callerSource: awf) are never counted as agent requests. Totals are unchanged.

Tests

  • The named acceptance tests from the issue are included, except the routed-smoke end-to-end case below. Fixtures are based on the real token-usage/v0.28.70 records and AWF's producer shapes from feat(api-proxy): attribute requests to the main agent or a sub-agent via x-awf-caller gh-aw-firewall#10222.
    • JS (awf_caller_attribution.test.cjs):
      • pi_main_and_subagent_caller_attribution (spawns a real child process that loads pi_provider.cjs)
      • copilot_sdk_main_and_subagent_caller_attribution
      • unsupported_engine_does_not_mislabel_subagents
      • invalid_or_missing_caller_is_absent_and_backward_compatible
      • awf_owned_purpose_wins_over_caller
    • Go:
      • TestProxyCallerPrecedesCorrelationAndPreservesFallback
      • TestRawProxyCallerAttributionWithoutUnifiedTokenUsage
      • TestUnsupportedEngineDoesNotMislabelSubagents, which compiles workflows for all five engines and asserts no provider- or process-wide caller header is configured.

Expected routed-smoke evidence (usage/aw_session.jsonl, not yet dispatched on this branch)

  • smoke-pi-routed: firewall.token_usage events should look like this:
    {"purpose":"agent","callerSource":"caller_header"}
    {"purpose":"subagent","agentName":"haiku-whoami","callerSource":"caller_header"}
    {"purpose":"subagent","agentName":"mini-whoami","callerSource":"caller_header"}
    {"purpose":"routing_classification","callerSource":"awf"}
  • smoke-copilot-sdk-routed: only the classifier gains callerSource: awf. Agent requests stay unattributed, so the SDK end-to-end case is unsupported, not passing.

Known check failures that also occur on main

  • golint flags only files this PR doesn't change: pkg/cli/spec_test.go and pkg/workflow/claude_engine.go.
  • The custom Go linter flags two lines in token_usage_subagent_session.go: the defer at line 172 and the slice indexing at line 1527 (line 1514 on main).

Copilot AI and others added 2 commits October 22, 2026 05:53
Copilot AI changed the title [WIP] Add x-awf-caller header support for main/sub-agent requests Attribute Pi main/sub-agent requests with x-awf-caller and preserve caller metadata Oct 22, 2026
Copilot AI requested a review from SivaKesava1 October 22, 2026 05:57
@SivaKesava1

Copy link
Copy Markdown
Collaborator

We reviewed the caller-attribution changes at 8b7426b6. The logic looks right:

  • The Pi header reaches AWF on the CLI, RPC and agent-core paths and in sub-agent child processes.
  • Validation matches AWF's caller-header.js exactly.
  • The collector keys match callerRecordFields.
  • The pkg/cli attribution is unchanged for runs that have no caller fields, and nothing is counted twice.
  • TestProxyCaller* and TestRawProxyCaller* pass.

Blocking: unrelated changes. The branch has about 250 changed files beyond the fix. Commit 33244f22 and the session-end commit "Apply remaining changes" (8b7426b6) contain:

  • Codemod edits to 22 workflow sources under .github/workflows/*.md, for example missing-tool: → report-missing-tool: and expires: 1 → expires: 1d (avenger.md, poem-bot.md, tidy.md, smoke-claude-sub-agents.md, …).
  • A rewrite of .github/dependabot.yml, and changes to .github/workflows/go.mod, .github/workflows/package.json and .github/workflows/requirements.txt.
  • docs/src/content/docs/reference/frontmatter-full.md (+690 lines) and docs/src/content/docs/agent-factory-status.mdx.
  • About 214 recompiled .lock.yml files. Most of these differ only by engine version drift (Copilot CLI 1.0.98→1.0.101, Claude Code 2.1.296→2.1.300), and 13 of them now conflict with main.

None of these belong to #70940. The PR touches no compiler code, so after merging main it should change no files under .github/workflows/.

Nits

  • unified-agent-session-specification.md (the caller-fields paragraph and the T-UAS-083 row) says AWF "v0.28.70 and later". The caller fields shipped in AWF v0.28.67 (gh-aw-firewall#10222). Say "v0.28.67 and later".
  • awf_caller_attribution.test.cjs builds a record with purpose: "threat_detection" and caller_source: "awf". AWF only ever writes purpose: "routing_classification" (routing-provider-executor.js). Use the real shape, or drop that case.

Copilot AI commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

We reviewed the caller-attribution changes at 8b7426b6. The logic looks right:

  • The Pi header reaches AWF on the CLI, RPC and agent-core paths and in sub-agent child processes.
  • Validation match...

Done in f9cd3c1, the merge 87f10e0, and e0d2c1b:

  • I restored .github/workflows/, .github/dependabot.yml, frontmatter-full.md and agent-factory-status.mdx to main, then merged main. There were no conflicts, and recompiling changed nothing.
  • The spec now says the caller fields need AWF v0.28.67 or later.
  • I removed the made-up threat_detection record. The test now uses only the real routing_classification shape.
  • git diff --name-only origin/main...HEAD lists only the Attribute main/sub-agent requests with x-awf-caller and preserve caller metadata #70940 files, and nothing is left uncommitted.

make agent-finish stops at golint. It reports 3 modernize/embedlit issues in pkg/cli/audit_diff.go, which matches main. That is a known failure on main. Because it stopped there, its later tests didn't run, so I ran the tests for the changed Go and JS files separately and they pass.

I couldn't mark the PR ready for review because I don't have a tool for that. Please mark it ready.

This branch has not been deployed

No deployments
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.

Attribute main/sub-agent requests with x-awf-caller and preserve caller metadata

2 participants