Skip to content

Provider hardcodes setting_sources=[], so workflows cannot use a target repo's skills or CLAUDE.md #501

Description

@joaomena

Problem

ClaudeAgentSdkProvider passes setting_sources=[] unconditionally (src/conductor/providers/claude_agent_sdk.py:944). No workflow can opt in, so a step can never load the settings tier of the repository it operates on.

That rules out a whole class of workflow: an agent working on a target repo cannot use that repo's own .claude/skills/, CLAUDE.md, or .claude/rules/*.md. The repo's conventions have to be duplicated into the workflow's prompts instead of being read from the repo.

Why the empty list is right as a default

Not a bug on its own. The SDK re-defaults an unset setting_sources to ["user", "project"] whenever skills is set, so an explicit [] is the only way to get a hermetic run — otherwise behaviour depends on whose machine started it. The gap is that there's no escape hatch, not that the default is wrong.

Why the existing options don't cover it

The CLI has --plugin-dir but no --skill-dir, and ClaudeAgentOptions.skills takes skill names, not paths. So the only way to reach a target repo's skills today is to synthesise a per-repo plugin manifest — a lot of machinery for something setting_sources already expresses.

Proposal

An opt-in runtime.provider.setting_sources accepting user / project / local, defaulting to [] so current behaviour is unchanged. Loading a tier stays the workflow author's explicit decision.

Two things this turned out to need beyond the plumbing, both found by running it:

  1. The Skill tool has to be granted when setting_sources is non-empty. CLI-discovered skills never pass through conductor's resolved skill list, so gating the grant on that list alone leaves the model seeing the repo's skills in its listing with no tool to invoke them.
  2. ClaudeAgentOptions.skills has to become "all" when tiers are enabled and the workflow named no skills. Otherwise every call fails with "not in this session's skills allowlist" — observed with 28 discovered skills, all rejected.

Security note

project loads the entire tier, hooks included. Pointing it at untrusted code means executing that code's hooks. Worth documenting explicitly at the schema. Keeping the default at [] means nobody gets this without asking. Whether user should be permitted at all is a fair question — it makes a run depend on the operator's machine.

Verified

Tested against claude-agent-sdk 0.2.87 with a fixture repo whose .claude/rules is a symlink to a tool-agnostic .agents/rules, and a CLAUDE.md that never references it. With setting_sources=[] the agent reports no rule; with ["project"] it returns the rule's contents and its marker token. So skills, CLAUDE.md, and .claude/rules all arrive through the one tier, symlinks included.

Happy to open a PR — we have this running on a fork and can upstream it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions