docs: align documentation with Java/Python SDK structure; remove all Agentspan naming (breaking) - #164
Merged
Conversation
Restructures the documentation to match conductor-oss/java-sdk, the
canonical layout that python-sdk#441 adopted:
docs/*.md core SDK topics (21 files)
docs/agents/concepts/ one file per agent concept (11)
docs/agents/frameworks/ one file per adapter (6)
docs/agents/reference/ lookup tables and schema (6)
Agent-layer pages are relocated from the existing writing-agents.md,
advanced.md, api-reference.md and framework-agents.md. Those four files
are untouched by this commit and become redirect stubs in a follow-up.
Core-SDK topic pages are new: this repo previously documented the core
SDK only in README.md and docs/readme/. Content is derived from the SDK
source; docs/metrics.md is carried over verbatim as observability.md.
Deviations from the Python set, both deliberate:
- frameworks/semantic-kernel.md added. The adapter is .NET-only and is
documented today in framework-agents.md; omitting it would drop
existing content.
- schema-client.md, langchain.md, langgraph.md and claude-agent-sdk.md
are status-banner stubs. The functionality does not exist in .NET, so
each states that plainly and points at the nearest supported path.
Env var names throughout use the CONDUCTOR_AGENT_* form. The code still
reads AGENTSPAN_* until the rename commit lands later in this branch.
agent-schema.json is hand-maintained against AgentConfigSerializer. This
repo has no schema verifier, unlike java-sdk; documentation-parity.md
records that gap along with the absent link checking.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Relocates the content that the previous commit's structure supersedes, leaving each old path as a pointer rather than deleting it, so existing inbound links keep working: docs/agents/writing-agents.md -> concepts/ docs/agents/advanced.md -> concepts/deploy-serve-run.md, stateful.md docs/agents/api-reference.md -> reference/ docs/agents/framework-agents.md -> frameworks/ docs/metrics.md -> observability.md docs/readme/workers.md -> workers.md docs/readme/workflow.md -> workflows.md Each stub carries a was/now table rather than a bare "moved" line — slightly longer than the equivalent python-sdk stubs, but a reader landing from an old link gets routed to the specific section instead of a directory index. metrics.md content was verified byte-identical in observability.md before being replaced. Also updated in-repo references that we control, since the stubs exist for external inbound links rather than for our own docs: - docs/agents/getting-started.md next-steps and AgentResult links - README.md worker link, plus a pointer to the docs index - Harness/README.md metrics link All 250 relative links under docs/ verified to resolve. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ases Renames the eight AgentConfig knobs from AGENTSPAN_* to CONDUCTOR_AGENT_*, matching the Java and Python SDKs, while keeping the legacy names as fallbacks. No action is required of existing users. Two prefixes coexist deliberately: connection settings stay CONDUCTOR_* because they are shared with the core SDK, while these knobs configure only the agent layer. This mirrors python-sdk#441's split — but unlike that PR, which deleted every AGENTSPAN_* read, the aliases are retained here. Resolution order per knob is CONDUCTOR_AGENT_<name> -> AGENTSPAN_<name> -> built-in default, via a single ResolveEnv seam. A blank or whitespace-only value is treated as unset so it falls through the chain; a *malformed* value falls back to the default rather than to the legacy name, so a typo cannot silently pick up stale configuration. Public type names are untouched. AgentspanException is the base of eight public exception types and AgentspanJson.Options appears in user code, so renaming either would be a breaking change for no functional gain. Tests: six new cases cover precedence, blank-skipping, malformed-value handling, and bool/double coverage. The pre-existing EachEnvVar_Honored test is left byte-identical so that it passing demonstrates the legacy names still work end to end, rather than merely that a fallback branch exists. Also corrects two docs from the previous commit that overstated blank-value handling for connection settings, and records the underlying defect in CHANGELOG under "Known issue": BuildConfiguration chains with ?? and so falls back only on unset, not blank, contradicting an earlier CHANGELOG claim. Connection resolution is left unchanged pending a decision. NOT COMPILED OR TESTED: no .NET toolchain is available in this environment. Changes are verified by inspection only and need CI or a local dotnet test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
BuildConfiguration chained CONDUCTOR_* -> AGENTSPAN_* -> default with ??,
which falls back only on null. On Unix, Environment.GetEnvironmentVariable
returns "" for a variable set to empty, so
export CONDUCTOR_SERVER_URL=
produced BasePath="" instead of falling through to AGENTSPAN_SERVER_URL and
then to http://localhost:8080/api. The auth key and secret had the same
defect, partly masked by the IsNullOrEmpty guard before
OrkesAuthenticationSettings was constructed.
Replaces the ?? chains with a FirstNonBlank helper so blank and
whitespace-only values are treated as unset at every step. This also covers
an explicitly-passed serverUrl and AgentRuntimeOptions.ServerUrl, where an
empty string previously became the BasePath verbatim.
CHANGELOG has claimed "blank env vars no longer clobber the fallback chain"
since the connection rename; that claim was untrue for the URL path and had
no test. It is now true and covered. The "Known issue" note added in the
previous commit is replaced with a Fixed entry, and the two docs describing
the old behaviour are updated.
Tests: five new cases — blank current name falls through to legacy, both
blank falls through to default, blank explicit arg falls through to env,
blank secret yields no auth settings, blank key pair falls through to legacy.
The six pre-existing tests are unchanged.
STILL NOT COMPILED: no .NET toolchain in this environment. Verified by
inspection; CI is the check.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
main advanced 10 commits since this branch was cut, including the server-driven guardrails work (#163). Two files conflicted because main edited the same pages this branch gutted to stubs: docs/agents/writing-agents.md docs/agents/api-reference.md Resolved to the stubs, but main's new content is carried forward into the new locations rather than discarded with the old files: - concepts/guardrails.md gains the "two kinds, two places" distinction — regex/llm guardrails are data-only and server-evaluated (no worker, HTTP client, or API key in-process), while custom [Guardrail] methods run in one combined worker per agent/tool scope. - reference/api.md drops the apiKey parameter from LLMGuardrail.Create, which main removed, and adds AgentHandle.PauseAsync/UnpauseAsync/Pause/Unpause. main also changed AgentConfigSerializer's guardrail serialization, so the hand-maintained schema was stale on arrival. agent-schema.json and agent-schema.md now document guardrailType (custom/regex/llm/external) and its type-specific fields: patterns/mode/message, model/policy/maxTokens, and taskName for the per-scope custom worker. Separately, corrects an error inherited from the old api-reference.md: it documented `OnFail onFail = Retry` for both RegexGuardrail.Create and LLMGuardrail.Create, but the code has defaulted to OnFail.Raise both before and after main's changes. Stage 1 copied that mistake faithfully into two new files; both now say Raise. Verified: 250 relative links resolve, no conflict markers, agent-schema.json parses, and the CONDUCTOR_AGENT_* rename plus FirstNonBlank survived the auto-merge of AgentRuntime.cs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests.
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
Renames the SDK-owned Agentspan naming across 183 files in
Conductor.AI.Examples and Conductor.AI.E2eTests, plus the agent-e2e workflow
env block.
Env vars:
AGENTSPAN_SERVER_URL -> CONDUCTOR_SERVER_URL
AGENTSPAN_LLM_MODEL -> CONDUCTOR_AGENT_LLM_MODEL
AGENTSPAN_WORKER_THREADS -> CONDUCTOR_AGENT_WORKER_THREADS
AGENTSPAN_WORKER_POLL_INTERVAL -> CONDUCTOR_AGENT_WORKER_POLL_INTERVAL
Prose "Agentspan server" -> "Conductor server". SDK-owned identifiers
(conductor-csharp-sdk / conductor-worker user agents, e2e skill-name prefixes,
/tmp session paths, the Kafka example's topic) renamed with both sides updated
together.
The blind-sed hazard was real: sweeping AGENTSPAN_SERVER_URL reproduced the
exact bug merged upstream in python-sdk#441 —
GetEnvironmentVariable("CONDUCTOR_SERVER_URL")
?? GetEnvironmentVariable("CONDUCTOR_SERVER_URL")
in Examples/Shared/Settings.cs and a 16h comment. Both rewritten deliberately.
A second, quieter regression was also introduced and fixed: four sites
previously read AGENTSPAN_SERVER_URL directly, so after the rename anyone with
only the legacy variable set would have silently got localhost. Examples 108
and 115 now use the shared Settings.ServerUrl, and E2eFixture/Suite2 carry the
CONDUCTOR_ -> AGENTSPAN_ -> default chain explicitly. Verified repo-wide that
no adjacent duplicate env read remains.
The prose sweep also produced "Conductor/Conductor server" and self-referential
"(or CONDUCTOR_SERVER_URL as a fallback)" lines; both cleaned up.
Deliberately NOT renamed, being externally owned — see the PR discussion:
- `agentspan credentials set ...` (21 refs) — an external CLI binary
- agentspan-ai GitHub org and its repos (8 refs) — live API URLs
- agentspan.default-context-window (2) — a server-side boot property
- agentspan-echo-group, agentspan-runtime, agentspan.test, `agentspan > 0.4.2`
- AgentspanJson, AgentspanE2eTests — public/test identifiers, per the
decision not to rename types
Also documents in getting-started.md that CONDUCTOR_AGENT_LLM_MODEL is an
examples convention, not something the SDK reads.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds Agentspan to the domain glossary as a retired term, so a future reader (or agent) doesn't reintroduce it as the product name, and notes the three places it legitimately survives: the retained AgentspanException / AgentspanJson type names, and externally-owned names outside this SDK's control. Adds docs/adr/0001-conductor-agent-env-naming.md, creating docs/adr/ lazily as the domain-doc convention specifies. The decision qualifies for an ADR on all three counts: env-var naming and alias posture are public surface and so hard to reverse; the end state looks like an abandoned migration and will provoke "why didn't they finish?"; and it was a real trade-off — cross-SDK parity over internal prefix consistency, API stability over a complete rebrand. The ADR also records the blank-vs-malformed asymmetry in the fallback chain, which is the least obvious part of the implementation: a blank current value falls through to the legacy name, but a malformed one falls back to the built-in default so a typo cannot silently resurrect stale config. docs/README.md gains a design-decisions section pointing at adr/ and CONTEXT.md, so neither is discoverable only by knowing it exists. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ambiorix2099
marked this pull request as ready for review
July 28, 2026 22:38
Review feedback: no backward compatibility. Reverses the alias decision this
branch originally shipped and inverts ADR-0001.
BREAKING (configuration + source):
- AGENTSPAN_* environment variables are no longer read. This covers the eight
agent runtime knobs and the three connection settings, the latter having
been honored as fallbacks since before this branch.
- AgentspanException -> ConductorAgentException
- AgentspanJson -> ConductorAgentJson
- OTel ActivitySource "agentspan.agents" -> "conductor.agents"
- AgentspanE2eTests namespace folded into Conductor.AI.E2eTests
No aliases, no [Obsolete] shims. Must ship as a minor or major bump.
Worth flagging for reviewers: the two failure modes differ. A renamed type is a
compile error, which is safe. A removed env var is NOT — an unrecognised
variable is indistinguishable from an unset one, so a missed rename surfaces as
unexpected default behaviour rather than an error. docs/upgrading.md leads with
that and gives a grep to find stragglers.
Tests assert the removal positively (LegacyAgentspanName_IsIgnored,
LegacyAgentspanServerUrl_IsIgnored, LegacyAgentspanAuthPair_IsIgnored, and a
per-knob sweep) so re-introducing a fallback fails the build rather than passing
quietly. The old precedence and blank-falls-through-to-legacy tests are gone —
their premise no longer exists.
Docs rewritten rather than patched, since several statements were now false:
upgrading.md now leads with a breaking-change banner and a migration table
instead of "no action required"; compatibility.md's "deprecations" section
became "removed surfaces"; documentation-parity.md no longer claims divergence
from Python on aliases, because we now match its actual behaviour. CHANGELOG
gains Removed/Not-renamed sections, and the older unreleased entry that claimed
the fallbacks were retained is corrected in place rather than left to
contradict this one.
Deliberately NOT renamed, being outside this SDK's control:
- the `agentspan` CLI, the agentspan-ai GitHub org, and server properties
such as agentspan.default-context-window
- __agentspan_ctx__, the task-input key the *server* uses to deliver
ToolContext. The SDK only ever reads it; renaming it would silently break
tool context injection.
NOT COMPILED LOCALLY: no .NET toolchain here. Verified by inspection —
no AGENTSPAN_ env reads remain, no old type names outside migration docs, 254
doc links resolve. CI is the check.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review feedback: "1:1 alignment with the docs, including READMEs." PR #441 did not only add files under docs/ — it also gutted several READMEs, moving their content into the new structure. The first pass here missed that, having scoped the target as the 43 doc files plus redirect stubs. Closing it: README.md (root) rebuilt as a navigation hub (-251/+…) Conductor.AI.Examples/README.md added — indexes the 175 agent examples The root README now follows python-sdk's section order (Choose your path / Choose your Conductor server / Why Conductor? / Requirements and compatibility / Install the SDK / AI agent quickstart / Workflow and worker quickstart / Common tasks / Troubleshooting / Support and project policies / License), so a reader moving between SDKs finds the same shape. 159 lines vs python's 186. The ~100-line inline Hello World is gone: it already exists verbatim in docs/core-quickstart.md, which this branch created, so the root README was carrying a duplicate that would have drifted. Configuration snippets likewise defer to connection-authentication.md and server-setup.md. The examples README is grounded in an actual directory survey rather than guesswork — 109 numbered (01-115), 36 Adk*, 20 Sk*, 10 OpenAi* — and documents which examples need more than a server and a model (MCP testkit, Kafka broker, GitHub token, stdin for the HITL ones). documentation-parity.md gains the verified counts, so the recurring "is it 1:1?" question is answered by the repo rather than by a person: top-level 21/21, concepts 11/11, reference 6/6, frameworks 5/5 (+1) => 43 of 43 present, zero missing It also explains why a directory listing of python-sdk's docs/ shows 33 files rather than 21: twelve are legacy SCREAMING_CASE documents predating the restructure that #441 never touched, whose content maps onto the new topic docs. Literal filename parity would mean importing files python-sdk has not finished retiring, so this SDK does not mirror them. And it states plainly that content parity is neither a goal nor desirable across languages. Verified: 97 relative links across the five index files resolve, all four root README anchors resolve, and 255 relative links under docs/ still resolve. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
v1r3n
approved these changes
Jul 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request type
NOTE: Please remember to run
./gradlew spotlessApplyto fix any format violations.Changes in this PR
Describe the new behavior from this PR, and why it's needed
Issue # (no tracking issue; ports the intent of python-sdk#441)
Why
conductor-oss/java-sdkis the canonical documentation structure, and python-sdk#441 adopted it. This repo was behind it: of the 43 doc files that PR added, this repo had none — noconcepts/,frameworks/, orreference/subdirectories, and none of the top-level topic docs. Java's CI actively rejectsdocs/agents/api-reference.mdas a retired path, and this repo had that file.The terminology half of the driver was equally real: 648 case-insensitive
agentspanoccurrences across 212 files, and 421AGENTSPAN_*references.What changed
602ec8fconcepts/, 6frameworks/, 6reference/5fca471b00ecc5CONDUCTOR_AGENT_*163104dc05037emain, carrying the server-driven guardrail content into the new locations3556498c50b648CONTEXT.mdglossary entry + ADR-000158fd00cEnv var naming. Eight
AgentConfigknobs renamed toCONDUCTOR_AGENT_*, matching Java and Python. Two prefixes coexist deliberately: connection settings stayCONDUCTOR_*because they are shared with the core SDK; these knobs configure only the agent layer.Bugfix (the
Bugfixbox above).AgentRuntime.BuildConfigurationchained with??, which falls back only onnull. On Unix,export CONDUCTOR_SERVER_URL=producedBasePath=""instead of falling through to the default. CHANGELOG had claimed this was already fixed since the connection rename; it wasn't, and had no test. Now fixed via aFirstNonBlankhelper and covered by tests.Build related.
.github/workflows/agent-e2e.ymlenv block updated to the new variable names.One name that is load-bearing and was NOT renamed
__agentspan_ctx__is a task-input key the SDK only ever reads — the server writes it. It is part of the wire contract forToolContextinjection, so renaming it would have silently broken tool context delivery with no compile error and no test failure. It is now called out in the ADR, CHANGELOG,upgrading.md, andCONTEXT.mdso nobody "finishes the job" later.Also untouched, being outside this SDK's control: the
agentspanCLI (21 refs), theagentspan-aiGitHub org and its repos (8), and server properties such asagentspan.default-context-window. Renaming these in docs would point users at things that may not exist. Note: if theagentspan-aiorg has already been renamed, several credential examples are already broken onmain— pre-existing, not caused here.Two upstream claims that did not survive verification
AGENTSPAN_*read, and its config docstring reads "OnlyCONDUCTOR_AGENT_*settings are supported." The docstring is the accurate one. This SDK now matches that actual behaviour, and goes further by renaming the public types too.AGENTSPAN_→CONDUCTOR_sweep left a merged bug upstream:os.getenv("CONDUCTOR_SERVER_URL") or os.getenv("CONDUCTOR_SERVER_URL")— the same variable read twice, silently dropping legacy support.My own sweep reproduced that second bug character-for-character in
Examples/Shared/Settings.cs; it was caught and rewritten.agentspan.embedded=true— a server-side boot property — appears zero times in this repo, so there was nothing to mishandle.Deviations worth reviewer attention
frameworks/semantic-kernel.mdadded beyond the Python set. That adapter is .NET-only and is documented today inframework-agents.md; writing only Python's five files would have destroyed existing content.schema-client.md,langchain.md,langgraph.md,claude-agent-sdk.md. The functionality does not exist in .NET, so each says so plainly and points at the nearest supported path rather than describing absent features.observability.mdismetrics.mdverbatim, verified byte-identical before the original was gutted.README.mdand two files underdocs/readme/. This is where review effort is best spent. Three API names written from memory (Skill.LoadAll,DynamicForkTask, and theonFaildefault) turned out wrong when checked against source; there is no link checker or schema verifier here to catch the next one.api-reference.mddocumentedOnFail onFail = Retryfor both guardrail factories, but the code defaults toOnFail.Raisebefore and after main's changes.Verification
58fd00c—lint,unit_tests,integration_tests,build_ai_examples,legacy_integration_tests.build_ai_examplespassing means all 175 example projects still compile after the type rename, which is the change most likely to have broken something.58fd00c: 157 tests, 155 passed, 2 skipped — identical counts to the pre-removal run onc50b648. This is the evidence that matters most for the alias removal:E2eFixturenow reads onlyCONDUCTOR_SERVER_URL, so if the workflow env and the fixture had drifted apart, the availability probe would have failed, every suite would have skipped, and the run would still have reported green. Matching counts confirm the suites genuinely reached a live server through the new variable alone.LegacyAgentspanName_IsIgnored,LegacyAgentspanServerUrl_IsIgnored,LegacyAgentspanAuthPair_IsIgnored, plus a per-knob sweep confirming every legacy name yields the default. Re-introducing a fallback fails the build rather than passing quietly.docs/verified to resolve;agent-schema.jsonverified to parse.Known gap
No documentation validation was added. Java enforces link checking, a retired-reference grep, and a schema verifier in CI; this repo has none. This is not theoretical:
agent-schema.jsonwent stale within hours of being written whenmainchangedAgentConfigSerializer's guardrail serialization, and only a manual re-check caught it. Recorded indocs/documentation-parity.md.Alternatives considered
Describe alternative implementation you have considered
Keep the
AGENTSPAN_*env aliases. This is what the branch originally shipped, and ADR-0001 was written to justify it: a fallback chain costs one line per knob, while dropping it costs every existing deployment's configuration. Reversed in review ("no backward compatibility"), because a partial rebrand leaves two names for one setting indefinitely and every reader has to learn which is canonical. The ADR was rewritten rather than amended, since its central section was "Why the aliases stayed".Rename the types behind an
[Obsolete]shim. InsertConductorAgentExceptionas a new base withAgentspanException : ConductorAgentExceptionmarked[Obsolete], so bothcatchclauses keep working. Rejected for the same reason as the aliases: permanent obsolete surface in the public API to spare a one-line edit in consumer code. A compile error is the right failure mode here — unlike the env vars, this one cannot fail silently.Rename
__agentspan_ctx__too, for a literally complete sweep. Rejected on evidence: the SDK only reads that key, so the server writes it. Renaming would breakToolContextinjection silently.One prefix everywhere (
CONDUCTOR_*for the runtime knobs too). Internally the most consistent, but it diverges from Java and Python, and would imply either that the core SDK reads worker-liveness knobs or that the agent layer owns the connection settings. Cross-SDK parity won.Delete the superseded doc pages instead of stubbing them. Cleaner final tree and unambiguously satisfies Java's ban on
docs/agents/api-reference.md, but breaks every inbound link. Python's own precedent was to gut rather than delete (writing-agents.mdwent +6/−477), so stubs it is — each carrying a was/now table so a stale link lands on the specific section, not a directory index.Mirror Python's file set verbatim, with no
semantic-kernel.md. Rejected because it would silently drop existing documentation for an adapter this SDK actually ships.Add the doc validation now (lychee + retired-reference grep as CI steps, schema contract as xUnit tests). Deferred deliberately to keep this PR reviewable; the gap is documented rather than left implicit.
Fix the blank-env-var defect in a separate PR. Considered, since it touches shared core-SDK connection resolution rather than the agent layer. Included here because the fix is small and this PR's docs would otherwise have had to describe behaviour known to be wrong.
🤖 Generated with Claude Code