Repository navigation
Pass request identity, lineage, and read-only state/notices handles to context providers #459
Description
Problem
A conventional src/providers/<name>.ts factory receives only { invocation, signal }. It cannot read the request's identity axes (host, session, workspace), its lineage, or the mounted state/notices handles, because generated scopes run providers before runAgentRequest opens the request. So a provider cannot expose a derived view of shared app state — which is exactly what examples/worktree-proximity's agent-topology provider was meant to be. The example ships it as a permanent unavailable stub, and routes read topology from (await agent()).state instead.
For the plugin use-case (a topology()/peers() accessor apps can call from any route), a provider is the natural home: it is typed by typegen, mounted once per request, and mockable through the route-unit fixture seam. Today that home cannot see the data.
Evidence (main @ 284141958)
packages/agent-bundle/src/routes/public.ts:95-102—AgentProviderContext = { invocation, signal };AgentProviderFactory = (context) => unknown.packages/agent-bundle/src/routes/provider-execution.ts:80-101—executeProviderscalls each factory with{ invocation, signal }only.packages/agent-bundle/src/build/entry-shell.ts:300-332— routed CLI:requestBindings()(state + noticeLedger) exist at:311, providers execute at:312-316, thenrunAgentRequest({ …, noticeLedger, providers, state })at:317-332. Same ordering for the rendered-route worker at:508-527.docs/entry-conventions.md:85, 217— public contract documents the factory as receiving{ invocation, signal }.examples/worktree-proximity/src/providers/agent-topology.ts:6-12— returns{ state: 'unavailable', reason: 'Topology snapshots are available only from the mounted request state handle; providers execute before that handle is mounted.' }.examples/worktree-proximity/README.md:42-43, 61-64: "providers execute before request state is mounted, so this provider reports an honest unavailable result and routes read snapshots from(await agent()).state.read()instead."- Add typed Agent request context and pluggable context providers #95's sketch had
resolve(request: AgentRequest); what landed (feat(routes): execute conventional context providers in generated request scopes (#95 remainder) #255) is narrower. Add typed Agent request context and pluggable context providers #95 also states providers "do not implicitly observe events or mutate durable state" — this proposal keeps that: read access only.
Proposed shape (small)
Widen AgentProviderContext with the read-only parts of the request, and open the request before the provider loop:
interface AgentProviderContext {
readonly invocation: AgentProviderInvocation;
readonly signal: AbortSignal;
// new, all read-only
readonly host: Observed<AgentHostIdentity>;
readonly session: Observed<AgentSessionIdentity>;
readonly workspace: Observed<AgentWorkspaceIdentity>;
readonly lineage: Observed<AgentLineage>;
readonly state?: Pick<AgentStateHandle, 'read'>;
readonly notices?: Pick<AgentNoticesHandle, 'inbox'>;
}Implementation sketch: in the generated scopes, run runAgentRequest with providers as a lazily-filled frozen record (or run the provider loop as the first step inside the request and freeze providers afterwards), so factories can call the same handles routes get. dispatch/publish stay off the provider surface (#95 stance). Providers that already destructure { invocation, signal } are unaffected.
Out of scope / related
- Provider dependency graphs / ordering beyond the current sorted-key order (Add typed Agent request context and pluggable context providers #95).
- Exposing the lineage tree itself (sibling issue, see "Related" comment); once both land,
agent-topologybecomes() => context.lineageplus the app's own intent state.
Acceptance
examples/worktree-proximity/src/providers/agent-topology.ts returns an available snapshot read from context.state.read() (or context.lineage) instead of the stub; src/mcp/coordinator/tools/status.tsx reads providers.agentTopology rather than withTopology(...); route-unit tests keep passing with the fixture seam (context.providers) and the cross-process suite packages/agent-bundle/tests/worktree-proximity-journeys.test.ts still shows exact-revision equality across processes. A framework test in entry-shell.test.ts proves a provider observes lineage and a read-only state on every generated surface.
Activity
ScriptedAlchemy commentedon Sep 3, 2026
Related: #457 (lineage tree on the request), #458 (lineage-addressed notices), #460 (publisher-scoped notice visibility). Context: #95 (provider contract as landed in #255), #104 (why
agent-topologyships as a stub).chore(examples): use built-in framework surface over hand-rolled setup (
docs(framework-mode): providers resolve after the request opens (#459 …
feat(providers): hand context providers the request identity, lineage…