@lead: issue #22 — per-agent skill scoping via permission.skill
This commit is contained in:
@@ -52,14 +52,20 @@ jobs:
|
||||
TOKEN_LEAD: ${{ secrets.TOKEN_LEAD }}
|
||||
TOKEN_QA: ${{ secrets.TOKEN_QA }}
|
||||
run: |
|
||||
# --- agent registry: model + capabilities + mode + role ---
|
||||
# --- agent registry: model + capabilities + mode + role + skills ---
|
||||
# `skills` is the allow-list of opencode Skills each agent may load. It scopes the
|
||||
# `permission.skill` block written into opencode.json below so an agent only ever sees
|
||||
# (and can load) the skills relevant to its role. Skills NOT listed here are hidden from
|
||||
# that agent entirely — not even the one-line summary appears in its <available_skills>,
|
||||
# so the full API/how-to detail never reaches an agent that shouldn't act on it. A teammate
|
||||
# can still learn *that* another agent has a capability from the roster and ask them to use it.
|
||||
cat > /tmp/agents.json <<'JSON'
|
||||
{
|
||||
"pm": {"model":"ollama-cloud/gemma4:cloud","vision":true, "mode":"comment","desc":"Product manager — research, plan, ask clarifying questions, and decide which dev should do the work. Comments only; never edits files."},
|
||||
"junior": {"model":"ollama-cloud/kimi-k2.7-code:cloud","vision":false,"mode":"pr", "desc":"Junior dev — small, low-risk changes (mostly YAML/compose/config). Text-only, cannot read images. Defers complex or image tasks to @senior or @lead."},
|
||||
"senior": {"model":"ollama-cloud/glm-5.2:cloud","vision":false,"mode":"pr", "desc":"Senior dev — complex, multi-file implementation (GLM-5.2 via Ollama Cloud, text-only)."},
|
||||
"lead": {"model":"anthropic/claude-opus-4-8","vision":true, "mode":"pr", "desc":"Tech lead — the hardest problems, architecture, and final calls."},
|
||||
"qa": {"model":"ollama-cloud/minimax-m3:cloud","vision":true, "mode":"comment","desc":"QA — verifies things work. Drives a headless browser (Playwright) to open a URL/web app, click through it, screenshot, and report bugs or confirm behavior. Comments findings; opens no PRs."}
|
||||
"pm": {"model":"ollama-cloud/gemma4:cloud","vision":true, "mode":"comment","skills":["gitea-api"],"desc":"Product manager — research, plan, ask clarifying questions, and decide which dev should do the work. Comments only; never edits files."},
|
||||
"junior": {"model":"ollama-cloud/kimi-k2.7-code:cloud","vision":false,"mode":"pr", "skills":[],"desc":"Junior dev — small, low-risk changes (mostly YAML/compose/config). Text-only, cannot read images. Defers complex or image tasks to @senior or @lead."},
|
||||
"senior": {"model":"ollama-cloud/glm-5.2:cloud","vision":false,"mode":"pr", "skills":["gitea-api","node1-ssh"],"desc":"Senior dev — complex, multi-file implementation (GLM-5.2 via Ollama Cloud, text-only)."},
|
||||
"lead": {"model":"anthropic/claude-opus-4-8","vision":true, "mode":"pr", "skills":["gitea-api","node1-ssh"],"desc":"Tech lead — the hardest problems, architecture, and final calls."},
|
||||
"qa": {"model":"ollama-cloud/minimax-m3:cloud","vision":true, "mode":"comment","skills":["gitea-api"],"desc":"QA — verifies things work. Drives a headless browser (Playwright) to open a URL/web app, click through it, screenshot, and report bugs or confirm behavior. Comments findings; opens no PRs."}
|
||||
}
|
||||
JSON
|
||||
# On a new issue, @pm auto-assesses. On a comment, route by the @mention.
|
||||
@@ -74,8 +80,10 @@ jobs:
|
||||
model=$(jq -r --arg a "$name" '.[$a].model' /tmp/agents.json)
|
||||
vision=$(jq -r --arg a "$name" '.[$a].vision' /tmp/agents.json)
|
||||
mode=$(jq -r --arg a "$name" '.[$a].mode' /tmp/agents.json)
|
||||
echo "Routing to @$name (model=$model vision=$vision mode=$mode)"
|
||||
{ echo "name=$name"; echo "model=$model"; echo "vision=$vision"; echo "mode=$mode"; } >> "$GITHUB_OUTPUT"
|
||||
# Compact JSON array of the skills this agent may load (scopes permission.skill below).
|
||||
skills=$(jq -c --arg a "$name" '.[$a].skills // []' /tmp/agents.json)
|
||||
echo "Routing to @$name (model=$model vision=$vision mode=$mode skills=$skills)"
|
||||
{ echo "name=$name"; echo "model=$model"; echo "vision=$vision"; echo "mode=$mode"; echo "skills=$skills"; } >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Act as the agent's own Gitea user when its token is set; else the built-in bot.
|
||||
case "$name" in
|
||||
@@ -108,6 +116,7 @@ jobs:
|
||||
OLLAMA_URL: ${{ secrets.OLLAMA_URL }}
|
||||
OLLAMA_CLOUD_API_KEY: ${{ secrets.OLLAMA_CLOUD_API_KEY }}
|
||||
NAME: ${{ steps.prep.outputs.name }}
|
||||
SKILLS: ${{ steps.prep.outputs.skills }} # JSON array of skills this agent may load
|
||||
run: |
|
||||
curl -fsSL https://opencode.ai/install | bash
|
||||
echo "$HOME/.opencode/bin" >> "$GITHUB_PATH"
|
||||
@@ -121,12 +130,23 @@ jobs:
|
||||
npx -y playwright install --with-deps chromium || npx -y playwright install chromium || true
|
||||
;;
|
||||
esac
|
||||
# Per-agent skill scoping. Skills are loaded on-demand by opencode: only a skill's one-line
|
||||
# `description` ever appears in an agent's <available_skills> list, and the full SKILL.md
|
||||
# body (curl/API how-to) is loaded ONLY when the agent calls the `skill` tool — it is never
|
||||
# in any system prompt. To also hide the summary from agents that shouldn't use a skill, we
|
||||
# deny all skills by default and allow only the ones in this agent's registry list. A denied
|
||||
# skill is hidden entirely (name + description omitted), so e.g. @junior never sees gitea-api
|
||||
# at all; it just knows from the roster that @senior/@lead can, and asks them.
|
||||
SKILLS="${SKILLS:-[]}"
|
||||
PERM=$(jq -nc --argjson s "$SKILLS" '
|
||||
{skill: ( {"*":"deny"} + (reduce $s[] as $k ({}; . + {($k):"allow"})) )}')
|
||||
# Two ollama providers: local self-hosted (ornith) + Ollama Cloud (gemma4/kimi-k2.7-code/glm-5.2/minimax-m3).
|
||||
jq -n --argjson mcp "$MCP" --arg url "$OLLAMA_URL" --arg ckey "$OLLAMA_CLOUD_API_KEY" '{
|
||||
jq -n --argjson mcp "$MCP" --argjson perm "$PERM" --arg url "$OLLAMA_URL" --arg ckey "$OLLAMA_CLOUD_API_KEY" '{
|
||||
provider: {
|
||||
ollama: {npm:"@ai-sdk/openai-compatible", options:{baseURL:($url+"/v1")}, models:{"ornith:35b":{}}},
|
||||
"ollama-cloud": {npm:"@ai-sdk/openai-compatible", options:{baseURL:"https://ollama.com/v1", apiKey:$ckey}, models:{"glm-5.2:cloud":{},"gemma4:cloud":{},"kimi-k2.7-code:cloud":{},"minimax-m3:cloud":{}}}
|
||||
},
|
||||
permission: $perm,
|
||||
mcp: $mcp
|
||||
}' > ~/.config/opencode/opencode.json
|
||||
echo "opencode config (secrets masked):"; cat ~/.config/opencode/opencode.json
|
||||
|
||||
Reference in New Issue
Block a user