Repository navigation
feat: strengthen agent action definitions using Claude Code subagent frontmatter conventions #80
Description
Problem Statement
askcc action prompts in askcc/definitions.py (and their user-overridable templates under ~/.askcc/templates/) are plain prompt strings. They lack the structural controls that Claude Code's native subagent format provides — no per-action tool allowlist, no model selection, no effort/thinking overrides, no permission mode, no maxTurns.
This means every action runs with the same tool surface, same model, and same effort level regardless of what it actually needs. That is suboptimal on three axes:
- Security / blast radius —
issue-review,validate,explore, anddiagnoseare analysis-only, yet they currently inherit fullEdit/Write/Bash(*)capability from the invokingclaudesubprocess. A misbehaving run could mutate the tree. - Cost — read-only analysis actions (
issue-review,explore,diagnose) do not need Opus-tier reasoning;developandplando. Today there is no way to declare this per-action. - Focus / prompt quality — Claude Code's official subagent best-practice is a tight frontmatter contract (narrow description, explicit tools, explicit model). askcc's prompts declare none of this at the definition layer.
Reference: https://code.claude.com/docs/en/subagents.md
Current State
askcc/definitions.py—AgentConfigcapturesaction_name,description,system_prompt,user_prompt_template, template filenames, andrequired_variables. No tool/model/effort/permission fields.~/.askcc/templates/*_SYSTEM_PROMPT.md— plain markdown, no frontmatter parsed.askcc/cli.py—--effort,--max-thinking-tokens,--disable-thinkingare global CLI flags applied uniformly to every action (cli.py:108-136).askcc/runners/— runners receive effort/thinking as a single value, no per-action override path.
Proposal
Adopt a Claude Code subagent-style frontmatter on each *_SYSTEM_PROMPT.md template file. load_agent_config parses it; the runner translates declared fields into claude CLI flags when spawning the subprocess.
Frontmatter schema (per-action, all optional except description)
---
name: develop
description: Implements a planned GitHub issue end-to-end; opens a PR linked to the issue.
tools: Read, Write, Edit, Bash, Grep, Glob, WebFetch
model: opus # or sonnet | haiku | inherit
effort: max # low | medium | high | xhigh | max
max_thinking_tokens: 32000
permission_mode: acceptEdits # default | acceptEdits | plan | bypassPermissions
max_turns: 200
---
You are an expert software developer operating inside Claude Code...Proposed per-action defaults
| Action | tools (allowlist) | model | effort | permission_mode | Rationale |
|---|---|---|---|---|---|
prepare |
Read, Grep, Glob, Bash(gh:*) | sonnet | medium | default | Analysis + gh comment/edit; no file mutation |
plan |
Read, Grep, Glob, Bash(gh:*) | opus | high | default | Heavy reasoning, no file mutation |
develop |
Read, Write, Edit, Bash, Grep, Glob | opus | max | acceptEdits | Full implementation authority |
issue-review |
Read, Grep, Glob, Bash(gh:*) | sonnet | medium | default | Read-only + gh comment |
pr-review |
Read, Grep, Glob, Bash(gh:,git:) | opus | high | default | Reads branch, posts review — no repo mutation |
explore |
Read, Grep, Glob, Bash(gh:*) | sonnet | high | default | Investigation only |
diagnose |
Read, Grep, Glob, Bash(gh:,git:) | sonnet | high | default | Root-cause analysis, no fixes |
fix-ci |
Read, Write, Edit, Bash, Grep, Glob | sonnet | high | acceptEdits | Narrow-scope code changes |
Values are defaults — existing global CLI flags (--effort, --max-thinking-tokens, etc.) and env vars continue to work and take precedence when explicitly set, preserving backwards compatibility.
Benefits
- Least-privilege tool surface per action —
issue-reviewcannot accidentallyEditfiles;validate/diagnosestay read-only. - Cost-appropriate model per action — heavy reasoning actions (
plan,develop,pr-review) on Opus; analysis actions on Sonnet. - Alignment with Claude Code conventions — users who read https://code.claude.com/docs/en/subagents.md will recognize the format. Templates become portable — a user can drop an askcc template into
.claude/agents/with minimal changes. - Structural validation at load time — a typo in
model: opuzfails fast atload_agent_config, not mid-run. - Discoverability —
askcc --helpand README can surface per-action defaults; users know what each action will and won't do.
Acceptance Criteria
-
AgentConfiggains optional fields:tools,disallowed_tools,model,effort,max_thinking_tokens,permission_mode,max_turns -
load_agent_configparses YAML frontmatter from*_SYSTEM_PROMPT.mdtemplate files when present; falls back to the existing plain-prompt behaviour when no frontmatter is found (backwards compatible) - Built-in
*_AGENT_PROMPTconstants inaskcc/definitions.pyare updated to emit frontmatter-bearing defaults matching the table above - Runner(s) translate declared frontmatter fields into
claudeCLI flags (--model,--allowedTools,--disallowedTools,--permission-mode,--max-turns, effort/thinking) - CLI flags and env vars (
--effort,--model,ASKCC_CLAUDE_EFFORT_LEVEL, etc.) continue to override per-action frontmatter when explicitly set - Invalid frontmatter values raise a clear error at load time with the field name and allowed values
- Existing user templates without frontmatter continue to work unchanged (back-compat)
-
bootstrap_templateswrites new defaults with frontmatter on first run; existing~/.askcc/templates/files are not overwritten - README documents the frontmatter schema, per-action defaults table, and override precedence
- Tests cover: frontmatter parsing, missing-frontmatter back-compat, CLI/env override precedence, invalid-value rejection
Dependencies
- Claude Code subagent docs: https://code.claude.com/docs/en/subagents.md
- Related but distinct: feat: refine action system prompts using OMX persona contracts as reference #62 (prompt content tightening via OMX personas) — focuses on the prompt body; this issue focuses on the declarative wrapper around it
- Related: Add contextual SOP/skill loading #64 (contextual SOP/skill loading) — complementary; skills could be declared alongside the frontmatter via a
skills:list
Non-Goals
- Does not change existing prompt content (that is feat: refine action system prompts using OMX persona contracts as reference #62's scope)
- Does not migrate askcc to invoke
.claude/agents/-resolved subagents; it only borrows the frontmatter convention for askcc's own template files - Does not remove the global CLI flags — they remain as per-run overrides
Notes / Open Questions
- Tool syntax: Claude Code allows
Bash(gh:*)style scoping. Decide whether askcc's defaults use coarseBashor scoped forms — the table above proposes scoped where practical. - Frontmatter parser: prefer a stdlib-only approach (
yamlis not stdlib). Options:tomllib+ TOML frontmatter, or addpyyamlas a dep. Recommendpyyamlto match the Claude Code ecosystem convention.
Activity
monkut commentedon Apr 25, 2026
Implementation in progress on
feature/80-agent-frontmatter— opened PR #84.Summary of changes
AgentConfig:tools,disallowed_tools,model,effort,max_thinking_tokens,max_turnsaskcc/functions.py(parse_frontmatter) — no new runtime deps; validates enum fields with clear errors at load timeload_agent_configto split frontmatter from body; templates without frontmatter continue to work unchanged (back-compat)ClaudeRunnernow emits--model,--allowedTools,--disallowedTools,--max-turnsfromAgentConfigfields0.2.6Deviation from acceptance criteria
permission_modewas intentionally not exposed as anAgentConfigfield or per-action default. askcc runsclaudewith--dangerously-skip-permissionsso the one-shot subprocess can execute unattended; if any permission check were to trigger, the run would deadlock with no human to answer the prompt. The per-actiontoolsallowlist is the safety boundary instead. A code comment nearDEVELOP_AGENT_PROMPTandFIXCI_AGENT_PROMPTexplains why those write-capable agents need the broadEdit/Write/Bashallowlist.Decision per maintainer guidance during the develop phase.
monkut commentedon May 16, 2026
PR #84 merged 2026-04-25 delivered the bulk of this issue. Outstanding gap from the acceptance criteria — runtime override of
model(AC #5 explicitly named--model) — is now tracked in #110. Thepermission_modefield omission is an intentional, documented deviation (askcc runsclaude --dangerously-skip-permissions; a permission prompt would deadlock an unattended run) and is not being filed as a follow-up.Closing in favor of #110.