feat: return workspace skill directory from read_skill - #26713
Merged
Conversation
Workspace skills live on the workspace filesystem, and the agent's read_file and execute tools already operate on that same filesystem. But the skill's absolute directory was never surfaced to the model, so bundled supporting files (for example a scripts/ helper) could only be read through the relative-path-scoped read_skill_file tool and could never be run. read_skill now returns "dir", the absolute skill directory, for workspace skills. The model can join it with a supporting file's relative path to read or run that file with read_file or execute. Personal skills are database-backed with no files, so dir is omitted for them.
Docs preview📖 View docs preview for |
Make the read_skill response field self-documenting. "dir" was terse, and "workspace_directory" would collide with the existing notion of the workspace working directory (ContextFileDirectory, execute's WorkDir); the value is the skill's own subdirectory, so "skill_directory" is clearer and unambiguous.
This reverts commit f7c4328.
mafredri
approved these changes
Jun 25, 2026
mafredri
left a comment
Member
There was a problem hiding this comment.
Approving. But think the description could use a re-think.
Address review feedback: trim the read_skill tool description to a breadcrumb that just notes workspace skills also return "dir" (the absolute skill directory), without prescribing read_file/execute usage or implying read_skill_file should be avoided. Also condense the in-function comment.
…ription The model already sees the "dir" field in the read_skill response, so calling it out in the tool description is redundant. Restore the original description; the field and the explanatory code comment stay.
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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
Workspace skills live on the workspace filesystem, and the agent's
read_file/executetools already operate on that same filesystem. But a skill's absolute directory was never surfaced to the model:<available-skills>catalog lists only name + description,read_skillreturned{name, body, files}wherefilesare relative names, andread_skill_fileis relative-path-scoped (it rejects absolute paths,.., and hidden files).As a result, a bundled
scripts/foo.shcould be read but never run, and the agent had no way to browse or glob the skill directory.Change
read_skillnow returnsdir, the absolute skill directory, for workspace skills. The model can joindirwith a supporting file's relative path and pass the result toread_fileorexecute(which share the same workspace connection), so bundled scripts are runnable and the directory is browsable. This matches how Agent Skills work incoder/muxandopenai/codex.diris omitted for them.read_skill_fileis unchanged and remains a path-safe convenience for reading supporting files.read_skill, not in the always-on catalog.Why this is safe
No new capability or boundary is crossed. The agent already has unrestricted workspace filesystem access through
read_file/execute; the relative-only restriction onread_skill_fileis a guardrail for that one convenience tool, not a sandbox around the agent.ChatMessagePart.SkillDirremainstypescript:"-"and is still stripped byStripInternal()from the API/SSE wire format sent to the frontend. This change only affects the model-facingread_skilltool response.Testing
go test ./coderd/x/chatd/chattool/(skill tool tests) and./coderd/x/chatd/(skill prompt/merge tests)gofmt,go vet,golangci-lint(clean), markdownlint (0 errors)Investigation & decision log
Root cause trace
agent/agentcontextconfig/api.godiscoverSkillssetsSkillDiron the skill context part.coderd/x/chatd/chattool/skill.gorenderSkillIndexemits only- <alias>: <description>.read_skillomitted it: theSourceWorkspacebranch returned onlyname,body, and relativefiles.read_skill_fileis dir-scoped:validateSkillFilePathrejects absolute/../hidden,LoadSkillFilejoinspath.Join(skill.Dir, relativePath)server-side.codersdk/chats.goStripInternal()zeroesSkillDirfor API/SSE responses (typescript:"-"), which is the frontend channel, not the LLM tool channel.Key insight
In
coderd/x/chatd/generation_preparer.go,read_file,execute, and the skill tools are all wired with the sameGetWorkspaceConn.executeruns viaconn.StartProcessandread_fileviaconn.ReadFileLines, both on the workspace filesystem where skills live. The agent was fully capable of reading/running bundled files; it just lacked the absolute path.Alternatives considered
files: [{path, abs}]) — heavier wire change; the singlediris sufficient since the model can join.read_skill_fileand hand over only the dir (pure Agent Skills model) — larger redesign; reasonable as a future simplification, out of scope here.PR generated with Coder Agents on behalf of @kylecarbs.