feat: target-state worker secrets via TaskDef.runtimeMetadata - #311
Merged
v1r3n merged 5 commits intoJul 10, 2026
Merged
Conversation
…ta (target)
Replace the interim __resolved_credentials__ enrich-script stamping with the
target PR #1255 mechanism: when embedded, the worker's TaskDef declares its
secret names on runtimeMetadata; the host resolves them at the SIMPLE task's
own poll and injects values onto the wire-only Task.runtimeMetadata (never
persisted, no JS injection, resolved at the right task).
- AgentService.registerTaskDef(String, List<String>) stamps runtimeMetadata
only when EmbeddedMode.isEmbedded() && names non-empty; standalone leaves it
empty (native execution-token pull still delivers).
- Worker-tool branch passes AgentCompiler.collectToolCredentials(config) names.
- Remove interim stamping: ToolCompiler workerCred helpers + enrich args,
JavaScriptBuilder workerCredJson params/vars/injection, setWorkerCreds calls
in AgentCompiler/MultiAgentCompiler.
- Pin conductorVersion to the local runtimemeta build (has TaskDef.runtimeMetadata).
- Replace ToolCompilerWorkerCredTest with WorkerRuntimeMetadataTest: asserts
runtimeMetadata declared when embedded, empty standalone, and the enrich
script no longer emits __resolved_credentials__ (validated fail-first).
System-task delivery unchanged (LLM keys via host AI integration; HTTP/MCP/
planner headers via ${workflow.secrets}).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…a (target) Switch all four SDK worker read-paths from the interim __resolved_credentials__ task-input key to the target Task.runtimeMetadata wire field (conductor-oss PR #1255): the host resolves the worker's declared TaskDef.runtimeMetadata secret names at the SIMPLE task's own poll and injects the values on the wire only — never persisted to task input. The native execution-token pull stays as the standalone fallback. - Java: WorkerManager.readRuntimeMetadata(task) reads task.getRuntimeMetadata(); dep bump conductor-client 5.0.1 -> 5.1.0 (+ mavenLocal for the local build); ReadResolvedCredentialsTest -> ReadRuntimeMetadataTest (fail-first validated). - Python: _dispatch reads task.runtime_metadata; test_resolved_credentials -> test_runtime_metadata (fail-first validated). - TypeScript: worker.ts reads task.runtimeMetadata (structural cast so it compiles against the current client until the OpenAPI type releases); drop the __resolved_credentials__ strip; new worker.test.ts host-delivered case (fail-first validated). credentials.test.ts accessor path already aligned. - C#: WorkerManager.ReadRuntimeMetadata(task) reads task.RuntimeMetadata; drop the input strip; RuntimeMetadataReadTests via reflection. Not built here (no dotnet). Client deps require releases carrying Task.runtimeMetadata; pins annotated to repin once those land. Ships together with the server switchover so a runtimeMetadata-declaring server is never paired with an SDK reading the old key. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…adata isn't clobbered The SDK self-registered each worker TaskDef with overwrite semantics, using a bare def. When embedded, the host server pre-registers the worker TaskDef and declares its secret names on TaskDef.runtimeMetadata (conductor-oss PR #1255) — overwriting with a bare def (the client TaskDef model carries no runtimeMetadata field) clobbered that and starved the host resolver, so Task.runtimeMetadata arrived empty and secrets never resolved. Fix, flag-free (no embedded prop): register create-only — create the TaskDef when absent, never overwrite one that exists. Embedded, the server's def (with runtimeMetadata) is left intact; standalone still gets the def created when missing. The existence check chooses correctly with no configuration, so it "just works" either way. - Python: ToolRegistry.register_tool_workers + the framework worker path use overwrite_task_def=False (conductor-python then does get_task_def → skip-if-exists → else register). - Java: WorkerManager.registerTaskDef checks metadataClient.getTaskDef first and skips when present. - Tests (fail-first validated): Python test_embedded_taskdef_registration asserts create-only; Java EmbeddedTaskDefRegistrationTest asserts no-overwrite-when-exists / create-when-absent. Surfaced by the local embedded webhook e2e. TS/C# SDKs don't self-register worker TaskDefs, so they were already correct. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
v1r3n
approved these changes
Jul 10, 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.
Summary
Target-state worker-secret delivery for embedded mode, replacing the interim
__resolved_credentials__enrich-stamping shipped in #307. Based onfeature/embedded-secret-toggleso the interim stays intact and this can be pointed at / reverted independently.Mechanism (conductor-oss PR #1255): the worker's
TaskDef.runtimeMetadatadeclares its secret names; the host resolves them at the SIMPLE task's own poll and injects the values onto the wire-onlyTask.runtimeMetadata— never persisted to task input, no JS injection, resolved at the right task. System-task delivery is unchanged (LLM keys via the host AI integration; HTTP/MCP/planner headers via${workflow.secrets}).Changes
Server (
conductor-agentspan)AgentService.registerTaskDef(String, List<String>)stampsTaskDef.runtimeMetadataonly whenEmbeddedMode.isEmbedded()&& names non-empty; standalone leaves it empty (native execution-token pull).__resolved_credentials__stamping (ToolCompiler / JavaScriptBuilder / AgentCompiler / MultiAgentCompiler).runtimemetaconductor build that carriesTaskDef.runtimeMetadata(repin to the published version once PR #1255 releases).WorkerRuntimeMetadataTest— runtimeMetadata declared when embedded, empty standalone, enrich script no longer emits__resolved_credentials__(fail-first validated).SDK read-paths (all 4) — swapped
__resolved_credentials__→task.runtimeMetadata, native token-pull kept as the standalone fallback:readRuntimeMetadata(task), dep →conductor-client:5.1.0), Python (task.runtime_metadata), TypeScript (task.runtimeMetadata, drop the input strip), C# (task.RuntimeMetadata, drop the strip).Coordination
Depends on 4 client-library releases that carry
Task.runtimeMetadata(separate PRs to conductor-oss/java-sdk, python-sdk, csharp-sdk, conductor-sdk/conductor-javascript). Dep pins are annotated to repin once those land. Server + SDKs must ship together — aruntimeMetadata-declaring server paired with an SDK reading the old key would starve the worker.Test evidence
Server + Java/Python/TS SDK unit tests green; each change validated fail-first (broke impl → test failed → restored). Live embedded e2e (persisted task input has no plaintext / no
__resolved_credentials__) pending local Orkes run.🤖 Generated with Claude Code
Test Evidence: