Skip to content

Keep AGENTSPAN_* env vars and AgentspanError working, and validate the agent schema - #151

Closed
ambiorix2099 wants to merge 2 commits into
mainfrom
fix/agent-compat-aliases-and-schema-verify
Closed

Keep AGENTSPAN_* env vars and AgentspanError working, and validate the agent schema#151
ambiorix2099 wants to merge 2 commits into
mainfrom
fix/agent-compat-aliases-and-schema-verify

Conversation

@ambiorix2099

Copy link
Copy Markdown

Two focused follow-ups to #147. Narrowed from #148 (now closed) to only what #147 didn't cover.

1. The rename is currently a silent break — a0235ea

#147 removed the AGENTSPAN_* names outright. Two of the three failure modes give the user nothing to go on:

What was set Now Symptom
AGENTSPAN_SERVER_URL Not read at all. resolveOrkesConfig's agent-layer tier was removed entirely, not renamed Silent. Falls through to http://localhost:8080 and fails against the wrong server
AGENTSPAN_AUTH_KEY / _SECRET Not read Silent. Unauthenticated requests
AGENTSPAN_WORKER_*, LIVENESS_*, STREAMING_*, AUTO_START_WORKERS, LLM_MODEL Not read Silent. Reverts to defaults
AGENTSPAN_LOG_LEVEL Not read Silent
import { AgentspanError } Renamed, no alias Loud — compile error

This restores all of them as deprecated fallbacks that warn once per name per process.

It does not re-litigate #147's design. Each legacy name maps to whatever the code reads now, rather than reintroducing the agent-layer connection tier #147 deliberately deleted — connection and auth stay on the core CONDUCTOR_* vars, agent behaviour knobs stay on CONDUCTOR_AGENT_*. The result is that #147's shape is preserved and the migration stops being breaking.

CONDUCTOR_* env → explicit config → deprecated AGENTSPAN_* → localhost:8080

AgentspanError returns as a direct alias — the same class object, not a subclass — so instanceof works in both directions and existing catch blocks keep working. Value and type are both exported, so const e: AgentspanError still compiles. Verified against the built dist/.

Two deliberate asymmetries, both commented in the code:

  • AGENTSPAN_LOG_LEVEL falls back silently — warning there would log through the very logger whose level is still being resolved.
  • e2e/helpers.ts carries its own fallback, because that suite ships as a release bundle for downstream repos and the SDK-level alias doesn't cover vars the harness reads directly.
  • The helper is duplicated between src/agents and src/sdk rather than shared, because AGENTS.md forbids the agent layer importing from src/sdk outside agent-client.ts and worker.ts.

Adds 14 tests. #147 mechanically renamed the existing suite, so without these the compat guarantee has zero coverage.

2. agent-schema.json ships unvalidated — 284c94d

#147 added docs/agents/reference/agent-schema.json — the wire shape AgentConfigSerializer emits, shared with the Python and Java SDKs — with nothing checking it. It can drift from the serializer silently, leaving a documented contract that quietly stops describing reality.

Adds scripts/verify-agent-schema.mjs, wired as npm run verify:agent-schema and run in the existing docs job. Follows the verify-dist.mjs pattern already in this repo rather than transliterating python-sdk's pytest approach.

It selects the Ajv entrypoint from $schema (the file is 2020-12; Ajv's default export is draft-07), validates all 19 e2e/_configs/ fixtures, and asserts 8 invariants resolved through the root $ref so they survive restructuring.

Two of those invariants encode the existing design rather than second-guessing it: agentConfig stays closed and tool stays open. additionalProperties: false on agentConfig is what makes this a real gate — adding a serializer field now fails CI until the contract is updated.

Good news from writing it: all 19 fixtures pass, so the contract #147 documented does match current serializer output.

Adds ajv ^8.17.1 explicitly. It was already there transitively via eslint, but a CI gate resting on a transitive dep is how gates silently stop running.

Verification

Check Result
Lint 0 errors, 360 warnings — identical to main
Unit tests 1580 / 80 suites (main: 1566 / 79)
tsc --noEmit Zero net new errors vs main (455 pre-existing both sides)
Build + verify:dist 6 entrypoints, ESM + CJS
Alias behaviour Verified against built dist/ — same class object, instanceof both ways
Env fallback Smoke-tested: warns once, resolves the legacy value
Schema verifier 19 fixtures + 8 invariants; negative-tested two ways
Existing branding grep Still passes

Note

AgentspanMetadata in the langchain and langgraph wrappers was left un-renamed by #147 while the error class was renamed. That's a naming inconsistency rather than a compat break, so I left it alone — flagging it rather than widening this PR.

🤖 Generated with Claude Code

ambiorix2099 and others added 2 commits July 29, 2026 08:56
The Agentspan -> Conductor rename (#147) was a hard break for existing
deployments. Nothing warned, and two of the three failure modes are silent:

  - AGENTSPAN_SERVER_URL / AUTH_KEY / AUTH_SECRET are no longer read at all.
    resolveOrkesConfig previously had an agent-layer tier; that tier is now
    gone, so an app configured this way falls through to the
    http://localhost:8080 default and fails against the wrong server with
    no indication why.
  - AGENTSPAN_WORKER_*, LIVENESS_*, STREAMING_*, AUTO_START_WORKERS and
    AGENTSPAN_LLM_MODEL silently revert to defaults.
  - AgentspanError was renamed with no alias, so `import { AgentspanError }`
    and `catch (e) { e instanceof AgentspanError }` stop compiling. That one
    at least fails loudly.

This restores all three as deprecated fallbacks. Each legacy name maps to
whatever the code reads *now* rather than reintroducing the agent-layer
connection tier #147 deliberately removed -- connection/auth stays on the
core CONDUCTOR_* vars, agent behaviour knobs stay on CONDUCTOR_AGENT_*.
That keeps #147's design intact while making the migration non-breaking.

  - src/agents/legacy-env.ts       readRenamedEnv(), warn-once per name
  - src/agents/config.ts           behaviour knobs via agentEnv()
  - resolveOrkesConfig.ts          AGENTSPAN_SERVER_URL/AUTH_* below explicit
                                   config, mapped to their CONDUCTOR_* names
  - src/sdk/helpers/logger.ts      AGENTSPAN_LOG_LEVEL -> CONDUCTOR_LOG_LEVEL
  - e2e/helpers.ts                 its own fallback: that suite ships as a
                                   release bundle, and the SDK-level alias
                                   does not cover vars the harness reads
                                   directly
  - src/agents/errors.ts           AgentspanError as a @deprecated alias

The error alias is a direct alias, not a subclass, so `instanceof` works in
both directions; the value and type are both exported so `const e:
AgentspanError` still compiles. Verified against the built dist: alias and
canonical are the same class object and subclasses match.

AGENTSPAN_LOG_LEVEL falls back silently -- warning there would mean logging
through the very logger whose level is still being resolved. The helper is
duplicated between src/agents and src/sdk rather than shared, because the
agent layer must not import from src/sdk outside agent-client.ts and
worker.ts (AGENTS.md).

Adds 14 tests. The existing suite was mechanically renamed by #147, so
without these the compat guarantee would have no coverage: fallback
resolution, canonical-wins precedence, empty-value handling, warn-once, and
alias identity.

Not addressed here, flagged only: AgentspanMetadata in the langchain and
langgraph wrappers was left un-renamed by #147 while the error class was
renamed. That is a naming inconsistency rather than a compat break, so it
is out of scope for this change.

Verified: lint 0 errors / 360 warnings (identical to main), 1580 unit tests
across 80 suites (main: 1566/79), zero net new tsc errors against main,
build + verify:dist clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
docs/agents/reference/agent-schema.json documents the wire shape
AgentConfigSerializer emits and the server's agent compiler consumes, shared
with the Python and Java SDKs. It shipped in #147 with nothing validating it,
so it can drift from the serializer silently -- the failure mode being a
documented contract that quietly stops describing reality.

Adds scripts/verify-agent-schema.mjs, wired as `npm run verify:agent-schema`
and run in the existing `docs` job. Follows the scripts/verify-dist.mjs
pattern this repo already uses rather than transliterating python-sdk's
pytest approach.

It compiles the schema under its declared dialect (2020-12 here; Ajv's
default export is draft-07, so the right entrypoint is selected from
$schema), validates all 19 fixtures in e2e/_configs/, and asserts 8
structural invariants resolved through the root $ref so they survive
restructuring: name required and identifier-patterned, agents recursive,
tools referencing the shared tool def, agentConfig closed and tool open.

Those last two encode the existing design rather than second-guessing it.
agentConfig having additionalProperties: false is what makes this a real
gate -- adding a serializer field now fails CI until the contract is
updated, which is the point.

Adds ajv ^8.17.1 as an explicit devDependency. It was already present
transitively via eslint, but a CI gate depending on a transitive dep is how
gates silently stop running.

Verified: the schema compiles and all 19 fixtures pass, so the documented
contract does match current serializer output. Negative-tested two ways -- a
config missing `name`, and one with an undocumented extra field (caught by
the closed contract) -- each fails as intended and returns to green. The
existing branding grep still passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Flag Coverage Δ
integration-v4-sm 41.52% <44.60%> (+0.05%) ⬆️
integration-v5-sdkdev 43.99% <44.60%> (+0.10%) ⬆️
unit 74.00% <100.00%> (+0.12%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/agents/config.ts 100.00% <100.00%> (ø)
src/agents/errors.ts 90.73% <100.00%> (+1.11%) ⬆️
src/agents/legacy-env.ts 100.00% <100.00%> (ø)
...reateConductorClient/helpers/resolveOrkesConfig.ts 100.00% <100.00%> (ø)
src/sdk/helpers/logger.ts 95.45% <100.00%> (+2.77%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ambiorix2099

Copy link
Copy Markdown
Author

Duplicate work

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.

1 participant