Skip to content

Add [run.agent] skill_dirs for workflow and automation runs - #751

Open
mikaoelitiana wants to merge 1 commit into
fabro-sh:mainfrom
mikaoelitiana:feat/run-agent-skill-dirs
Open

Add [run.agent] skill_dirs for workflow and automation runs#751
mikaoelitiana wants to merge 1 commit into
fabro-sh:mainfrom
mikaoelitiana:feat/run-agent-skill-dirs

Conversation

@mikaoelitiana

Copy link
Copy Markdown

Closes #746

Problem

Skill discovery for workflow and automation runs was fixed to the three convention directories (~/.fabro/skills, {git_root}/.fabro/skills, {git_root}/skills). SessionOptions.skill_dirs existed in the agent SDK, but it is set at Session construction and had no run/workflow/project/settings TOML surface — [run.agent] only exposed fabro_tools and [run.agent.mcps]. A repository keeping its skills in .agents/skills/ (the Open Agent Skills / Claude Code convention) therefore could not surface them to workflow agents, and the documented symlink workaround does not work by design: glob follows a symlinked search root but deliberately does not recurse through symlinks below it.

Change

[run.agent] skill_dirs — extra skill discovery directories, resolved like every other run setting (workflow.toml, .fabro/project.toml, settings.toml) and carried through the persisted run spec into every agent session the run creates.

[run.agent]
skill_dirs = [".agents/skills"]

Semantics:

  • Additive. Configured directories are searched after the conventions, so a skill defined in one overrides a same-named convention skill, and nothing is lost by adding a directory.
  • Repo-relative. A relative entry resolves against the repository root (git root, falling back to the sandbox working directory), so it means the same thing regardless of a stage's working directory. Absolute entries are used verbatim.
  • Layers like other lists. A higher layer's list replaces a lower layer's unless it splices with "...".
  • Agent stages and their subagents both see the extra directories. Duplicates and blank entries are dropped.

The additive behavior lands in a new SessionOptions.extra_skill_dirs rather than reusing skill_dirs, so skill_dirs keeps its replace-the-defaults meaning for SDK callers and fabro exec --skills-dir.

Plumbing

[run.agent] skill_dirs (RunAgentLayer) → RunAgentSettings.skill_dirs → run spec → LlmSpec.skill_dirsAgentApiBackend::with_skill_dirsSessionOptions.extra_skill_dirsSession::initialize skill discovery.

RunAgentSettings.skill_dirs is #[serde(default)] so run specs persisted before this field stay loadable.

Docs

  • agents/skills.mdx — the new key, its additive/precedence rules, how it differs from the SDK's skill_dirs, and the symlink behavior that made the .fabro/skills/<name> symlink workaround fail (issue ask 3).
  • execution/run-configuration.mdx[run.agent] field table.
  • reference/user-configuration.mdx — regenerated with cargo dev docs refresh.
  • fabro-api.yamlRunAgentSettings.skill_dirs.

Tests

  • Resolver: default-empty, declared order, higher-layer replacement, "..." splice.
  • extend_skill_dirs: appended last, absolute passthrough, trailing-slash doc root, duplicate/blank skipping, empty no-op.
  • Session: extras appended to the conventions and to an explicit skill_dirs override.
  • Worker: [run.agent] skill_dirs reaches LlmSpec.
  • Workflow backend end-to-end: a skill in a configured .agents/skills directory is discovered through AgentApiBackend::run against a mock provider.

cargo build --workspace, the workspace test suite, cargo +nightly-2026-04-14 fmt --check --all, and clippy --workspace --all-targets -D warnings are clean. Two insta snapshots that dump resolved settings were updated for the new field.

Note: bun/Java were unavailable locally, so lib/packages/fabro-api-client/src/models/run-agent-settings.ts was hand-edited to match what bun run generate emits for the schema addition; worth a regeneration check.

🤖 Generated with Claude Code

Skill discovery for workflow and automation runs was fixed to the three
convention directories. `SessionOptions.skill_dirs` existed in the agent
SDK but was only settable by constructing a `Session` in Rust, so a
repository keeping its skills elsewhere (`.agents/skills`, the Open Agent
Skills convention) had no configuration-driven way to surface them.

Add `[run.agent] skill_dirs`, resolved like every other run setting and
carried through the run spec into each agent session. Configured
directories are *added to* the conventions and searched last, so a skill
defined there overrides a same-named convention skill; relative entries
resolve against the repository root. Subagents inherit the directories.

The additive semantics land in a new `SessionOptions.extra_skill_dirs`
rather than reusing `skill_dirs`, which keeps its replace-the-defaults
meaning for SDK callers and `fabro exec --skills-dir`.

Also document that skill discovery follows a symlinked search root but
does not recurse through symlinks below it, which is why symlinking
`.fabro/skills/<name>` at a directory elsewhere in the repo never
registered.

Closes fabro-sh#746

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

skill_dirs is not configurable for workflow/automation runs (skills stuck to convention dirs)

1 participant