Problem
The Auth subsystem that landed in #73 covers single-host agent execution well: WP_Agent_Token distinguishes multiple bearer tokens (and via client_id, multiple chat-bridge logins) for the same agent, and WP_Agent_Capability_Ceiling enforces that an agent never exceeds its owner's capabilities.
What's not yet in the substrate: a primitive for tracking cross-site agent-to-agent invocation chains. When agent A on host X invokes agent B on host Y over an authenticated request, host Y currently has no documented way to recover "this is an A2A call", "the calling agent is X", "this is depth N in a chain rooted at request R".
The reference shape is shipping in Extra-Chill/data-machine at inc/Core/Auth/CallerContext.php (referenced from inc/Abilities/PermissionHelper.php). It is populated by AgentAuthMiddleware from a small set of HTTP headers (X-*-Caller-* and X-*-Chain-*) after bearer-token resolution.
This pattern is universal across multi-agent hosts. Any substrate consumer that supports remote agent invocation will eventually reinvent it. Better to settle the contract in the substrate so adopters can implement against one shape.
Proposed shape
Generic value object plus a token authenticator hook:
final class WP_Agent_Caller_Context {
public function __construct(
public readonly string $caller_agent_id, // '' = top-of-chain
public readonly int $caller_user_id, // 0 = no user-on-caller-host
public readonly string $caller_host, // 'self' | absolute URL of remote host
public readonly int $chain_depth, // 0 = top-of-chain
public readonly string $chain_root_request_id, // stable identifier for the originating request
public readonly array $metadata = array(), // host-owned extension payload
) {}
public function is_cross_site(): bool {
return 'self' !== $this->caller_host && '' !== $this->caller_host;
}
}
Resolution would happen alongside token resolution in the existing WP_Agent_Token_Authenticator flow:
- Token authenticator resolves bearer token →
WP_Agent_Token.
- Authenticator parses caller-chain headers →
WP_Agent_Caller_Context.
- Both attach to the request execution principal.
Contract concerns to nail
- Header naming:
X-Agents-Api-Caller-Agent, X-Agents-Api-Caller-User, X-Agents-Api-Caller-Host, X-Agents-Api-Chain-Depth, X-Agents-Api-Chain-Root — substrate names so consumers don't diverge.
- Trust model: caller headers are claims, not assertions. Hosts MUST verify they trust the caller_host before honoring the chain — usually via a pre-shared key or mutual TLS. The substrate ships only the value object + parser; trust enforcement is a host concern.
- Loop / depth limits:
chain_depth exists to enable substrate-level loop protection (refuse to invoke at depth > N). Default ceiling needs a number — proposing 16 as a starting point that comfortably covers realistic agent collaboration patterns and refuses runaway recursion.
- Composition with
IterationBudget: chain depth is a natural budget dimension. Worth considering whether to expose it as IterationBudget('chain_depth', N) integration rather than a separate enforcement path.
Acceptance criteria
- Substrate exposes the value object and a documented header convention.
- A token authenticator can populate caller context alongside
WP_Agent_Token resolution.
- Execution principal carries the caller context through the conversation loop so policy adapters can consult it.
- Smoke tests cover: no-headers (top-of-chain context), valid chain, depth-limit enforcement, malformed headers (rejected fail-closed).
- Trust enforcement is documented as out-of-scope (host concern), with guidance on the recommended pattern.
AI assistance
- AI assistance: Yes
- Tool(s): Claude Code (Opus 4.7)
- Used for: Identifying the cross-site A2A primitive missing from the just-shipped Auth subsystem and drafting the contract proposal grounded in data-machine's reference impl.
Problem
The Auth subsystem that landed in #73 covers single-host agent execution well:
WP_Agent_Tokendistinguishes multiple bearer tokens (and viaclient_id, multiple chat-bridge logins) for the same agent, andWP_Agent_Capability_Ceilingenforces that an agent never exceeds its owner's capabilities.What's not yet in the substrate: a primitive for tracking cross-site agent-to-agent invocation chains. When agent A on host X invokes agent B on host Y over an authenticated request, host Y currently has no documented way to recover "this is an A2A call", "the calling agent is X", "this is depth N in a chain rooted at request R".
The reference shape is shipping in Extra-Chill/data-machine at
inc/Core/Auth/CallerContext.php(referenced frominc/Abilities/PermissionHelper.php). It is populated byAgentAuthMiddlewarefrom a small set of HTTP headers (X-*-Caller-*andX-*-Chain-*) after bearer-token resolution.This pattern is universal across multi-agent hosts. Any substrate consumer that supports remote agent invocation will eventually reinvent it. Better to settle the contract in the substrate so adopters can implement against one shape.
Proposed shape
Generic value object plus a token authenticator hook:
Resolution would happen alongside token resolution in the existing
WP_Agent_Token_Authenticatorflow:WP_Agent_Token.WP_Agent_Caller_Context.Contract concerns to nail
X-Agents-Api-Caller-Agent,X-Agents-Api-Caller-User,X-Agents-Api-Caller-Host,X-Agents-Api-Chain-Depth,X-Agents-Api-Chain-Root— substrate names so consumers don't diverge.chain_depthexists to enable substrate-level loop protection (refuse to invoke at depth > N). Default ceiling needs a number — proposing 16 as a starting point that comfortably covers realistic agent collaboration patterns and refuses runaway recursion.IterationBudget: chain depth is a natural budget dimension. Worth considering whether to expose it asIterationBudget('chain_depth', N)integration rather than a separate enforcement path.Acceptance criteria
WP_Agent_Tokenresolution.AI assistance