Feature proposal: product-session attribution and observability envelope for subagent providers #1493
Replies: 6 comments 1 reply
|
The durable product-session pointer proposed here would solve the immediate audit gap. I would also treat it as the first optional layer of a broader external-subagent lifecycle contract. The current final-text provider can remain the baseline. Providers could advertise extra capabilities when they support them:
Instead of making every provider implement these methods, For Codex, the bridge already observes thread and turn identifiers internally. Persisting an opaque reference would let a later delegation continue the same product session when the backend allows it. Progress and approval events could enter the parent as typed subagent events rather than being collapsed into the final tool result. I would keep this separate from the attribution plugin proposed above:
A small first slice would persist the external session reference, expose provider capabilities, and support cancellation acknowledgement. Continuation and approval forwarding could follow without changing the result contract for final-text-only providers. |
|
子代理 provider 的可观测性(session 归属/观测包络)——子代理是黑盒时排障很痛苦,归属到 product-session + 观测包络能打通全链路。 和 #1498(provider 配置)、#1442(子代理模型选择)一起,子代理体系正在完善。第 9 章子代理配置可作参考:https://github.com/Electricitysheep/dsh-handbook/blob/main/docs/09-mcp-subagent-workflow.md |
Field report: the plugin sketch is now boot-testedA minimal implementation of steps 1–2 from the proposal was built and mounted
New finding that sharpens the proposal: the durable log-only event (step 1) Happy to open the PR for either half, or both, if this direction is welcome. |
|
Code for the boot-tested sketch is now public, tagged for discoverability: https://github.com/jeremy9682/dsh-observability (
Both packages install via |
|
Thanks for taking the time to spec this out — the three-piece split matches how we now see it too: (1) core support for durable events owned by external plugins, (2) the attribution plugin built on it, (3) a separate provider-lifecycle proposal. Agreed that (3) should not be mixed into this thread. One thing our source re-check sharpened: the read side already implements the envelope-marker contract you describe. In the current tree:
So the actual gap in the harness is narrow, and piece (1) becomes two precise changes plus wiring: (a) Append-side append<T extends SessionEventType>(
type: T,
data: SessionEventMap[T],
...opts: T extends SurfaceEventType
? [opts: SurfaceIntent & { readonly ignorable?: false }]
: [opts?: { readonly ignorable?: true }]
): SessionEvent<T>Runtime rules: surface types may never set (b) Downstream registration surface. A small host-plane registry service (new package, mirroring ctx.sessionEvents.register({
type: 'dsh-codex-observability/run-attributed', // namespaced namespace/name
owner: 'dsh-codex-observability',
schemaVersion: 1,
decode: (data: JsonValue) => unknown, // throws on invalid data
}): () => voidConflict rules — all enforced at registration time, i.e. before the first append: un-namespaced type → refuse; type shadowing a Acceptance test — your four steps verbatim, run against both persistence backends (JSONL and SQLite):
Plus an export-survival test: a log containing an unknown ignorable event round-trips through copy/export without losing the event. Our current plugins ( We are happy to open the PR for (a) + (b) together. Two design points we'd flag for maintainer review before we start: whether the registry should live on the host plane or the agent plane (we lean host, matching |
|
配套实现仓库已进入社区插件目录:awesome-dsh-plugin 收录 PR https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/pull/274(dsh-observability,含中文 README)。文件 journal 的过渡方案可安装: |
Uh oh!
There was an error while loading. Please reload this page.
Feature proposal: product-session attribution and observability envelope for subagent providers
Summary
@deepseek-ai/dsh-subagent-codexis a one-shot bridge: each run startscodex app-server --stdio, creates one ephemeral thread, submits one task, andreturns only the final answer. What it does not retain is any durable
pointer back to the product's own session artifact. We run a local
governance layer (
agent-run, a small open wrapper around the same CLIs) whosewhole value is exactly that pointer, and we believe the gap is worth closing in
DSH itself — as an opt-in plugin, not a change to the provider contract.
What we verified in the current source
packages/subagent/subagent-codex/src/wire.tskeepsthreadId/turnIdasprivate protocol state (
private threadId: string | undefined); nothingwrites them to the parent Session.
only — reasoning, commentary, intermediate messages, tool traffic, usage,
stderr, and workspace diffs remain product-local"; the ephemeral thread id and
turn id "are never persisted in the parent Session"; there is "no wall-clock
timeout".
tool/call+ finaltool/result, but nosession_refpointing at~/.codex/sessions/2026/08/14/rollout-*.jsonl. Reconstructing "what did theCodex child actually do" from the DSH session alone is impossible.
What our wrapper returns for the same runs (real envelopes)
One read-only smoke task through
codex exec --json, and one through Cursor'sCLI, both unattended:
{ "run_id": "a7385536-…", "provider": "codex", "seat": "codex-smoke-test", "exit_code": 0, "failure_class": "none", "duration_ms": 55268, "session_id": "01a000ff-…", "session_ref": "~/.codex/sessions/2026/08/14/rollout-2026-08-14T11-58-35-….jsonl", "session_status": "attributed-stream-json", "model": "gpt-5.6-terra", "model_observed": "gpt-5.6-terra" }{ "provider": "cursor", "seat": "founder-smoke-cursor", "session_ref": "~/.cursor/chats/6a7822…/0890528f-….jsonl/store.db", "session_status": "attributed-correlated-artifacts", "model": "auto", "model_observed": "cursor-grok-4.5-high-fast", "model_family": "xai" }The attribution is a before/after fingerprint of the product's session root:
exactly one changed artifact →
attributed-*; zero →not-observed; several →ambiguous-concurrent-artifacts.model_observedis parsed from the provider'sown events, so an
autoroute that silently lands on a different model isdetected. Idle gaps during model reasoning are bounded by a per-provider idle
timeout distinct from the total deadline.
Proposal: an opt-in observability plugin, on existing extension points
SessionEvent(declaration-merged intoSessionEventMap) carrying{ provider, runId, sessionRef, sessionStatus, modelObserved, failureClass }, appended when the outer tool result settles.The pointer becomes part of the durable log, consistent with the
"model-visible ⟺ logged" convention (the pointer itself is log-only).
tools/resultobserver takes before/after fingerprints ofconfigurable provider session roots (same
roots-per-provider shape ourmanifest uses) and fills
sessionRef/sessionStatus.current "caller cancels" stance is documented as deliberate, so this stays
opt-in configuration rather than a default change.
model before the provider discards them, and record it in the same event.
No changes are required to
dsh-subagent's result contract or to the app-serverwire protocol. Real-composition tests and the persistence-catalog entry would
ship with the plugin, per the repo's testing policy.
Why it matters
subagent produced, instead of only its final answer.
auto/undisclosed routes that land on anunexpected model become visible in the session log.
failure_class(context-window, idle, total, providerfailure) survives into the log instead of collapsing into one error string.
only a root list + adapter, not a new provider.
Prior art in this repo's discussions (checked 2026-08-14)
Searched existing discussions before filing; none covers product-session
attribution for subagent providers. Adjacent work, each with a different scope:
verification receipts and hash chains over DSH's own session events. It never
sees the child product's local traffic, because
subagent-codexreturns finaltext only — exactly the gap this proposal closes.
exports the parent session as OTel traces; same blind spot for child-internal
activity, and no pointer to the product's own transcript artifact.
wire/CLI seams for Windows support; not run attribution.
a lifecycle UI bug, not observability of external runs.
#504,
#505,
#518,
#881,
#1211 —
Codex-as-LLM-provider community plugins (OAuth/subscription). Orthogonal:
they make Codex a model route; this proposal attributes external subagent
runs after the fact.
Happy to open a PR for the plugin if this direction is welcome. Filed for
discussion before implementation per the project's contribution guidance.
All reactions