Skip to content

fix: pass dispatch InlineConfig to GetAgent so volumes are applied#103

Merged
ptone merged 1 commit intoGoogleCloudPlatform:mainfrom
Empiria:fix/dispatch-inline-config-volumes
Apr 11, 2026
Merged

fix: pass dispatch InlineConfig to GetAgent so volumes are applied#103
ptone merged 1 commit intoGoogleCloudPlatform:mainfrom
Empiria:fix/dispatch-inline-config-volumes

Conversation

@meatballs
Copy link
Copy Markdown
Contributor

Summary

Fixes #101 — Hub-dispatched agents do not apply harness config or template volumes.

Root cause: When AgentManager.Start() builds the startInlineConfig to pass to GetAgent(), it only extracts HarnessAuth from opts, discarding opts.InlineConfig entirely. The InlineConfig carries volumes, env vars, image, and other settings from templates and harness configs that the hub sends via the dispatch request.

The broker correctly receives the InlineConfig from the hub (via buildStartContext in start_context.go), and GetAgent already merges it via config.MergeScionConfig — but the connection between the two was missing.

Fix: Use opts.InlineConfig as the base for startInlineConfig, then overlay HarnessAuth on top. This is a 7-line change in pkg/agent/run.go.

Before

var startInlineConfig *api.ScionConfig
if opts.HarnessAuth != "" {
    startInlineConfig = &api.ScionConfig{AuthSelectedType: opts.HarnessAuth}
}

After

var startInlineConfig *api.ScionConfig
if opts.InlineConfig != nil {
    startInlineConfig = opts.InlineConfig
}
if opts.HarnessAuth != "" {
    if startInlineConfig == nil {
        startInlineConfig = &api.ScionConfig{}
    }
    startInlineConfig.AuthSelectedType = opts.HarnessAuth
}

Test plan

  • go build ./pkg/agent/... — compiles cleanly
  • go vet ./pkg/agent/... — no warnings
  • Tested with self-hosted hub + remote broker — custom volumes (vault mount, SSH agent, model cache) now appear in the container
  • Verify local mode (--no-hub) still works (InlineConfig is nil, no change in behavior)
  • Verify HarnessAuth override still takes precedence

When the hub dispatches an agent, it sends an InlineConfig containing
volumes, env vars, image, and other settings from templates and harness
configs. The broker correctly receives this in StartOptions.InlineConfig,
but AgentManager.Start() only extracted HarnessAuth from the options,
discarding the rest of the InlineConfig.

This caused custom volume mounts (e.g. knowledge vaults, model caches,
SSH agent forwarding) to be silently dropped for hub-dispatched agents.
Only the 3 standard SCION mounts appeared.

Fix: pass opts.InlineConfig as the startInlineConfig to GetAgent(), which
already merges it via MergeScionConfig. HarnessAuth is overlaid on top.

Fixes GoogleCloudPlatform#101
@ptone
Copy link
Copy Markdown
Member

ptone commented Apr 11, 2026

PR #103 Review: fix: pass dispatch InlineConfig to GetAgent so volumes are applied

Reviewer: Scion Code Review Agent
Date: 2026-04-11
Branch: fix/dispatch-inline-config-volumes
Files changed: pkg/agent/run.go (+11 / -4)


Executive Summary

Risk Level: Low. This is a focused 7-line fix that aligns AgentManager.Start() with the existing pattern already used in AgentManager.Create() (via ProvisionAgent at provision.go:184-190). The change is structurally sound and addresses a clear data-flow gap where opts.InlineConfig was being silently discarded on the Start path.


Critical Issues

None.


Observations

1. Aliasing vs. Copying opts.InlineConfig — Acceptable but Worth Noting

if opts.InlineConfig != nil {
    startInlineConfig = opts.InlineConfig  // pointer alias, not copy
}

This assigns the pointer directly rather than making a shallow copy. Line 97 then mutates the struct in-place:

startInlineConfig.AuthSelectedType = opts.HarnessAuth

This means opts.InlineConfig.AuthSelectedType is mutated as a side-effect when HarnessAuth is non-empty.

Verdict: Not a bug in practice. The identical pattern already exists in ProvisionAgent (provision.go:184-189) where inlineCfg := opts.InlineConfig followed by inlineCfg.AuthSelectedType = opts.HarnessAuth performs the same aliased mutation. The opts struct is not reused after this call in either code path, so the mutation is harmless. However, if StartOptions is ever reused (e.g., retry logic), this would become a latent bug.

Optional defensive fix (not blocking):

if opts.InlineConfig != nil {
    copied := *opts.InlineConfig
    startInlineConfig = &copied
}

2. GetAgent Receives the Config via Variadic — Correct Usage

GetAgent accepts inlineConfig ...*api.ScionConfig and indexes inlineConfig[0] at provision.go:1019-1020, then passes it through to ProvisionAgent which calls MergeScionConfig(finalScionCfg, inlineCfg). This merge is additive (override-wins), so passing the full InlineConfig (with volumes, env, image, etc.) is exactly the right thing to do — these fields will layer on top of template defaults.

3. Comment Quality

The updated block comment (lines 85-88) is clear and explains the why — specifically calling out the silent-drop failure mode. This is good practice.


Positive Feedback

  • Consistency: The fix mirrors the exact pattern already established in ProvisionAgent (lines 184-190), making the two entry points (Start vs Create) consistent. This is the right approach.
  • Minimal blast radius: Only the config-assembly block was touched; no signatures, no new dependencies, no behavioral changes to GetAgent or MergeScionConfig.
  • Good PR description: The before/after comparison and root-cause analysis in the PR body make the intent unambiguous.

Final Verdict

Approve. The change is correct, minimal, and consistent with existing patterns. The pointer-aliasing observation is a minor defensive-programming note, not a blocking concern given identical usage elsewhere in the same package.

@ptone ptone merged commit 955eecf into GoogleCloudPlatform:main Apr 11, 2026
1 check passed
scion-gteam bot pushed a commit to ptone/scion that referenced this pull request Apr 12, 2026
…oogleCloudPlatform#103)

When the hub dispatches an agent, it sends an InlineConfig containing
volumes, env vars, image, and other settings from templates and harness
configs. The broker correctly receives this in StartOptions.InlineConfig,
but AgentManager.Start() only extracted HarnessAuth from the options,
discarding the rest of the InlineConfig.

This caused custom volume mounts (e.g. knowledge vaults, model caches,
SSH agent forwarding) to be silently dropped for hub-dispatched agents.
Only the 3 standard SCION mounts appeared.

Fix: pass opts.InlineConfig as the startInlineConfig to GetAgent(), which
already merges it via MergeScionConfig. HarnessAuth is overlaid on top.

Fixes GoogleCloudPlatform#101
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.

Hub-dispatched agents do not apply harness config or template volumes

2 participants