feat: add agent skills and use_agent to /strands command#48
feat: add agent skills and use_agent to /strands command#48agent-of-mkmeral wants to merge 3 commits intostrands-agents:mainfrom
Conversation
|
I don't want to set up separate workflows. it should be under the same strands command so it works in all repos where we have strands command already |
Integrates new capabilities directly into the existing /strands command instead of a separate /strands-beta workflow, so all repos with /strands get the new features automatically. Changes to existing files: - process-input.cjs: Add adversarial-test and release-digest modes - agent_runner.py: Add use_agent tool + AgentSkills plugin loading - action.yml: Checkout and copy agent-skills to working directory New files: - agent-skills/task-adversarial-tester/SKILL.md - agent-skills/task-release-digest/SKILL.md New /strands commands: - /strands adversarial-test — Break PRs with edge case tests - /strands release-digest — Generate release digests with sub-agents Existing commands unchanged. Skills load gracefully — if agent-skills/ directory doesn't exist or AgentSkills plugin isn't available, the agent works exactly as before.
7e65ade to
d2cc8ed
Compare
|
Reworked per your feedback — everything is now integrated into the existing What changedBefore (6 new files, 0 modifications):
After (3 modifications, 2 new files):
How it worksAny repo with
If the |
|
no, so i want like a separate agent with it's own runner, sowe can add more tools, plugins to it. but our changes should have no impact to the normal agent. that said, i want it to use the same pipeline overall, so don't recreate everything. like make agent creation configurable or something. so |
Reworked per @mkmeral's feedback — the beta agent is a separate agent with its own runner, but goes through the same pipeline. Design: - agent_runner.py: UNCHANGED from main (zero impact on normal agent) - beta_agent_runner.py: NEW — imports shared infra from agent_runner.py, adds AgentSkills plugin + use_agent tool - process-input.cjs: Routes /strands beta <command> through same pipeline with agent_type='beta' flag - action.yml: Reads agent_type, conditionally runs the right runner and only copies agent-skills for beta How it works: - /strands <command> → standard agent (exactly as before) - /strands beta <command> → beta agent (skills + use_agent + extensible) - Same pipeline: parse → run → finalize - Beta-only modes (adversarial-test, release-digest) auto-promote to beta
|
Reworked per your feedback @mkmeral — the beta agent now has its own runner, but uses the same pipeline. What changed in this commit
The flowSame pipeline (parse → run → finalize). Different agent. Diff vs main5 files changed, 511 insertions, 10 deletions. Zero modifications to |
|
|
||
| let systemPrompt; | ||
| if (skillName) { | ||
| systemPrompt = `You are an autonomous GitHub agent powered by Strands Agents SDK. |
There was a problem hiding this comment.
I mean we should probably have a meaningful system prompt right? check your own system prompt, check the existing SOPs, agent guidelines and so on. Let's have a proper system prompt
There was a problem hiding this comment.
Done in fffde45. Created BETA_SYSTEM_PROMPT.md based on:
- My own system prompt structure
- Agent Guidelines
- Skills/sub-agent context
The system prompt covers: identity, guidelines (add value or stay silent, keep it short, prove don't opine), capabilities overview, behavioral rules, output format, and anti-patterns.
Loaded by both process-input.cjs (reads the file for INPUT_SYSTEM_PROMPT) and beta_agent_runner.py (_load_system_prompt() with fallback).
| # Add beta-only tools (use_agent is already imported at module level) | ||
| # Check if use_agent is already in the list (it is in the current version) | ||
| tool_names = {getattr(t, '__name__', str(t)) for t in tools} | ||
| if 'use_agent' not in tool_names: |
There was a problem hiding this comment.
let's also add strands-agents/tools#387 to here, you can just create the tool here for now
There was a problem hiding this comment.
Done in fffde45. Added programmatic_tool_caller.py as a local copy from strands-agents/tools#387.
The beta runner tries to load it in priority order:
from strands_tools import programmatic_tool_caller(when it merges into the tools package)- Local copy via
importlib.utilfromscripts/python/programmatic_tool_caller.py - Graceful skip if neither available
Once tools#387 merges, the local copy becomes a no-op fallback.
| plugins = [] | ||
| skills_plugin = _load_skills_plugin() | ||
| if skills_plugin: | ||
| plugins.append(skills_plugin) |
There was a problem hiding this comment.
can we also activate a certain skill already based on the next word after beta? similar to SOPs,we can just invoke a skill like agent.tool.skills("activate", "reviewer") (check skills tool description to make sure lol, i just made the signature up)
There was a problem hiding this comment.
Done in fffde45. The correct signature is agent.tool.skills(skill_name="task-reviewer") (checked the skills tool description 😄).
Implementation:
process-input.cjsoutputsagent_mode(e.g.,reviewer,implement,adversarial-test) in the parsed JSONaction.ymlreads it and passes asAGENT_MODEenv varbeta_agent_runner.pyhas aSKILL_MAPthat maps modes → skills and calls_activate_skill_for_mode(agent, mode)after agent creation
Mapping:
/strands beta review → task-reviewer
/strands beta implement → task-implementer
/strands beta refine → task-refiner
/strands beta adversarial-test → task-adversarial-tester
/strands beta release-notes → task-release-notes
/strands beta meta-reason → task-meta-reasoner
/strands beta release-digest → task-release-digest
| @@ -0,0 +1,108 @@ | |||
| --- | |||
| name: task-adversarial-tester | |||
There was a problem hiding this comment.
add the meta reasoning skill too
also can we use the currently existing SOPs as skill too (without duplicating the files?) maybe we can just copy/paste on runtime, rename the files/folders and add frontmatter?
There was a problem hiding this comment.
Done in fffde45.
Meta-reasoner: Added task-meta-reasoner/SKILL.md with the full meta-reasoning gate SOP.
SOPs as skills (no duplication): Implemented runtime conversion in _convert_sops_to_skills():
action.ymlcopiesagent-sops/to the working directory alongsideagent-skills/- At runtime,
beta_agent_runner.pyreads.sop.mdfiles, adds YAML frontmatter (name, description, allowed-tools), and writes them asSKILL.mdin the skills directory - Dedicated skills (like
task-adversarial-tester) take precedence — if aSKILL.mdalready exists, the SOP is skipped - No source files are modified — it's a one-way write into the skills dir
So task-implementer.sop.md → agent-skills/task-implementer/SKILL.md at runtime, with proper frontmatter injected.
… SOP conversion 1. Meaningful system prompt (BETA_SYSTEM_PROMPT.md) - Created proper system prompt based on agent guidelines - Loaded from file by both process-input.cjs and beta_agent_runner.py 2. Programmatic tool caller (strands-agents/tools#387) - Added local copy of programmatic_tool_caller.py - Beta runner loads from strands_tools first, falls back to local copy 3. Skill activation based on command mode - /strands beta review → activates task-reviewer skill - /strands beta implement → activates task-implementer skill - Maps all modes to their corresponding skills via SKILL_MAP - agent.tool.skills(skill_name=...) called after agent creation 4. Meta-reasoner skill + SOPs as skills - Added task-meta-reasoner/SKILL.md - Runtime SOP→skill conversion: reads .sop.md files, adds YAML frontmatter, writes as SKILL.md — no source file duplication - Existing dedicated skills take precedence over converted SOPs 5. Pipeline changes - process-input.cjs outputs agent_mode in parsed JSON - action.yml reads agent_mode, passes as AGENT_MODE env var - action.yml copies agent-sops to working dir for conversion - Added meta-reason command routing
|
Addressed all 4 review threads in
Diff summary6 files changed, 724 insertions, 36 deletions. |
Summary
Adds a beta agent with its own runner to the
/strandscommand. The beta agent has extended capabilities (skills, sub-agents) while the standard agent remains completely unchanged.Design: Same pipeline, different agent
Both go through the same pipeline: parse → run → finalize. The only difference is which runner executes.
Changes to Existing Files
agent_runner.pyprocess-input.cjs/strands beta ..., setagent_typeflag, route modesaction.ymlagent_type, conditionally run the right runner + skills setupNew Files
beta_agent_runner.pyagent_runner.py, adds AgentSkills plugin +use_agenttoolagent-skills/task-adversarial-tester/SKILL.mdagent-skills/task-release-digest/SKILL.mdNew Commands
/strands beta/strands beta adversarial-test/strands beta release-digest/strands beta implement/strands beta reviewExisting commands (
/strands,/strands implement,/strands review,/strands refine,/strands release-notes) are completely unchanged.How the beta agent differs from standard
agent_runner.pybeta_agent_runner.pyuse_agentArchitecture
beta_agent_runner.pyimports shared infrastructure fromagent_runner.py:_get_all_tools()— base tools (beta adds on top)_setup_langfuse_telemetry()— telemetry setup_get_trace_attributes()— trace attributes_send_eval_trigger()— eval triggersSTRANDS_MODEL_ID, etc.)This means the beta agent automatically inherits any improvements to the shared infra without duplication.
Closes the intent from #43. cc @mkmeral