Skip to content

Role agents for spec-driven software development #37

Open

Description

@harsha09

Summary

Role agents are software-development teammates inside this SDD repo. A role has one job, a durable description, its own conversation, and an approval boundary. The person messages it about the product. It prepares work from the spec and the change pack, uses the team's development tools, and stops when an action needs a decision.

Grok Bot is the inspiration for that shape: one job, a lasting description, a run that continues until it must ask, a visible handoff, and an approval before a consequential action. This is not a clone of Grok Bot. There is no general-purpose assistant, no X, no voice product, and no second hosted computer. The source of truth stays the git repo: memory/, changes/, and .sdd/.

Setup is a message, not a spec form. The operations are sdd role commands. A later page calls those commands. sdd agents install stays what it is today: it installs one host stub (sdd, sdd-planner, sdd-implementer, sdd-reviewer) for Copilot, Claude, Grok, Ollama, or Kilo. It does not create a product role.

A draft that the person might accept is checked by a different role. That handoff is the accuracy loop: plan from the accepted spec, draft, critique, revise, then one plain-language stop.

Status

Approved for development on 2026-10-18. The issue stays open until the work ships. This issue is an epic for the role agents. The web product is a separate epic and is not part of these slices.

This revision fixes the conflicts below. The earlier diagram reviews were of older drafts and are not an approval of this text.

  • A first reading ends when the person accepts or corrects it. That is the decision. It does not use Allow once, Always allow, or Deny.
  • Allow once applies only the action named on the stop. A file edit does not also commit, push, open a pull request, tag, or deploy. Commit, push, open a pull request, merge, tag, and deploy run only when the stop names that action and the person allows it.
  • A role still cannot accept a spec, replace a decision, write a QA result, generate the release record, run sdd next, run sdd complete, or call createChange. No approval grants those.
  • Frontend and backend of one product stay one change pack, unless the person has named them as separate services in the spec.
  • Looking up a role or a run log is not the code-search work in Epic: pluggable local search and token/cost budgets for sdd context #21–Search S0 / Metrics: per-phase time, input/output tokens and cost tracking (sdd report) #26.
  • A shared role is a markdown file in the repo. Slack and Teams are how the team hears about the work. This issue does not add hosted private chats or accounts.
  • A stalled plan can be rebuilt once. The diagram no longer loops.
  • sdd role run --with the same role exits before any model call.

Build it in the order under Development order. The first slice is sdd role in this repo. Connectors and a page come after that slice.

Where this is built

Build it in this repository. Do not open a second product repo.

Piece Where it goes
Role runner, task network, approval check packages/core, new modules. Not more cases in commands.ts.
sdd role commands packages/cli, thin wrappers over core.
Host stubs Unchanged: packages/core/src/agents.ts and sdd agents install.
Role files The product repo being built, .sdd/roles/<name>.md, committed.
Run log Gitignored .sdd/role-runs/. Not .sdd/handoff.md.
Specs and decisions Markdown in memory/ and changes/<id>/, same ids the CLI already uses.
Tool connectors Outbound clients, same idea as .sdd/mcp.yaml. They seed a change or report status. Stage progress stays in the change pack.

One product is one sdd root. Frontend and backend of that product are one change pack. A module or a service exists only when the person has named it in the spec. It is a folder inside that root, not another sdd init. The runner must not call createChange, sdd next, or sdd complete, and it must not take the engineer's active change. sdd --no-agent still completes a pack with no model. There is no inbound MCP server that drives sdd next.

A separate repo would only be a different product: a hosted multi-tenant studio. That is outside this roadmap. Do not start it from this issue.

What a role must not do

A role cannot:

  • accept a spec
  • replace a decision
  • write a QA result
  • generate a release
  • run sdd next or sdd complete
  • call createChange

Allow once, always-allow, a routine, a handoff, a lead, and a connected tool cannot grant those. The runner rejects the call before it runs. Memory, a skill, and a tool cache are not the spec and not the decision list.

Commit, push, tag, open a pull request, merge, and deploy are not in that list. They run only when the stop names that exact action and the person allows it. Allowing a file edit does not commit it.

The stop shows the action and its inputs in the person's words. It does not show a diff. It does not undo work already completed.

Role

A role has a name, a label, one job, a durable description, and an approval boundary. The description holds the standing rules. The message holds the task. An empty job writes nothing and exits non-zero.

Commands: sdd role create, sdd role edit, sdd role pin, sdd role hide, sdd role show, sdd role duplicate, sdd role delete.

  • Pin keeps it at the top of the list.
  • Hide removes it from the main list and does not pause its routines.
  • Duplicate names the copy "<name> copy" and copies the profile, settings, skills, routines, and boundary. It does not copy the conversation, memory, or attachments.
  • Delete removes the profile, the conversation, and the routines that role owns. Files in the product repo remain.

Each role has its own conversation and memory. Memory may keep stable preferences and summaries. The person can correct a stale memory. A consequential claim cites the spec, the decision, or the tool that holds the current record. Changing memory leaves the spec and the QA result unchanged.

Examples, each with a job: spec steward, builder, QA author, release editor, module lead, product lead.

Conversation

The person opens a role and messages it about the product. They can paste text and links, attach files, mention a role, group, routine, or tool with @, invoke a skill with /, reply to one message, and send another instruction while work is in progress. "Stop now" ends the turn and does not undo a finished action.

Attachments are product material: specs, screenshots of the app, logs, PDFs, spreadsheets, source, and notebooks. The person says what each file is. The role does not modify the original unless the task says so.

The transcript shows tool calls, files, questions, and approval requests. The person can list roles and past runs from this product's .sdd/ files. That lookup is not the code-search work in #21–#26.

The first surface is the CLI. sdd role run --task "..." is the message. A later page may send the same command. The page is not part of the first slice.

Development tools

The person connects the tools the software team already uses. @ attaches a connected tool to a task. A connector is preferred over clicking through the site. Sign-in uses Take over. The secret is masked, kept out of the transcript, and not shown to the model.

Work Tools
Plan and track Jira, Azure DevOps Boards, GitHub Issues, GitLab Issues, Asana, Linear, Aha
Repos and review GitHub, GitLab, Bitbucket, Azure Repos
Build and ship Jenkins, GitHub Actions, GitLab CI, Azure Pipelines, CircleCI, JFrog Artifactory, JFrog Xray
Team conversation Slack, Microsoft Teams
Quality and runtime SonarQube, Sentry, PagerDuty, Datadog
Docs and design Confluence, Notion, Figma

Reading a record can sit inside the boundary: an issue, a pipeline result, a test report, an artifact version, a board status. Creating, updating, commenting as the person, opening a pull request, merging, deploying, promoting an artifact, and paging someone stop for approval. A missing source is reported. The role does not invent a ticket, a build result, or a passing check.

Slack and Teams receive a draft in the direct conversation. The person sends it. The draft is not posted to the channel by the role.

The product workspace is the repo and the app under test. Roles on the same product can read files saved there for a handoff. That workspace is not a personal computer for unrelated sites, and separate roles are not a security boundary inside it.

Coordination

Roles run in parallel. The person is not the router.

Handoff. One role messages another. The receiver wakes, does the task, and can reply later. Both conversations show the handoff and the spec or tool record involved. One owner per stage. The person can turn messaging between roles off.

Group. A group is the roles for one change or one connection spec. Approval requests and outgoing Slack or Teams drafts stay in the direct conversation.

Accuracy loop. When a draft is checked against an accepted spec, a different role critiques it. This is Andrew Ng's reflection pattern: one role drafts, another critiques against external evidence, the author revises. Sources for the pattern: Ng's March 2024 agentic-design letters, and the DeepLearning.AI Agentic AI course at https://www.deeplearning.ai/courses/agentic-ai/. No benchmark percentage is an acceptance number. One model call that plays both roles does not count.

sdd role run <author> --task "<one task>" --with <other-role> loads both role files. The same role as --with exits non-zero, calls no model, and writes no record.

  1. Plan once from the accepted section. The runner stores the check ids. The model does not decide that a spec covers the task. Code, a scenario, or a release with no accepted section stops before a draft. A first reading of the person's sentence may be drafted and does not accept the spec.
  2. Draft, then critique, then revision only when the critique names a gap. Cap 3 passes. An empty gap list ends the loop.
  3. The runner checks cites. Each gap cites a plan-check id, or the section id plus its decision id. A revision names the gaps it changed. A bad critique or revision spends that pass. Pass 4 calls nothing.

The log is gitignored .sdd/role-runs/<run-id>.jsonl, written between provider calls. The runner does not commit it. Each provider call carries one role id.

Skills and routines

A skill is how to do one development task: when to use it, inputs, steps, how to check it, what to return, and what needs approval. / invokes it. The person can save a skill from a completed task.

A routine belongs to one role and runs on a schedule or on a narrow development event, such as a failed main build or a merged pull request. The person confirms the owner, schedule, input, expected result, boundary, and what happens when the source is missing. A missing source is reported. Stale data is not substituted.

The person can test, edit, pause, resume, read history, and delete a routine. History is the run log in the product repo. A routine may propose a QA result. It cannot write one. A routine does not advance sdd next or sdd complete.

Approvals

The stop shows the action in the person's words.

  • Allow once performs that action and does not allow the next different action.
  • Always allow saves a rule for the same tool and the same inputs. The runner decides the match.
  • Deny applies nothing.
  • Ask first always stops a match. If it overlaps always-allow, the run stays stopped.

An approval from a routine, a tool event, or another role waits. If nobody answers before the timeout in .sdd/ config, the record shows Expired and the action does not run. The default timeout is 10 minutes. Saving a rule from an expired card does not run the action.

User journey

Maya does not use a terminal. She chooses a folder for a new product, or for code she already has. She says, "I can never find last month's hotel charge." Her words stay. She sees a short reading and accepts or corrects it. That acceptance is the decision. The work is inside Expenses, so that role prepares the change and stops in her words. She allows it once. She comes back, accepts a scenario, tries it, and records the result in her words against that change.

Later she says, "When an expense is reimbursed, the invoice in Billing should show it." Those parts are not connected. She sees a short plan and accepts it before anyone writes. She allows each action. A failing required scenario blocks the release until she accepts that failure. The reading stays the same. She chooses the release. The notes use her sentence. Generate release attaches those notes and does not deploy or push. If a git tag cannot be written, the release still exists and says the tag was not written.

A bug keeps what happened and what she expected on the page after a draft exists. The fix waits until she accepts the reading.

flowchart TD
  newProduct[New product: she chooses a folder and says what she needs]
  existing[Existing code: she chooses the folder]
  bug[Something broke: what happened, and what she expected]
  words[She says the need in her words]
  reading[She sees a short reading]
  accepted[She accepts it. Her words stay. This is the decision]
  corrected[She corrects it and sees the reading again]
  held[Not yet. The draft stays a draft]
  route{What the product shows}
  action[One part, or parts already connected: the action in her words]
  plan[Parts not connected yet: a short plan]
  planYes[She accepts the plan before anyone writes]
  checked[If a second role checked it: one sentence that it matches the reading she accepted]
  deny[Deny: nothing is applied]
  once[Allow once: that action runs. The reading, the try, and the release stay hers]
  always[Always allow: the same action may run again. She still accepts, records, and releases]
  scenario[She comes back, accepts a scenario, and tries it]
  result[She records pass or fail in her words, for this change]
  good[The required try passed]
  blockedRelease[She cannot choose the release yet]
  failOk[She accepts that failure. The reading stays the same]
  choose[She chooses what is in the release]
  notes[The notes use her sentence]
  ship[Generate release attaches those notes]
  stays[The decision, the result, and the release stay]

  newProduct --> words
  existing --> words
  bug --> words
  words --> reading
  reading --> accepted
  reading --> corrected
  reading --> held
  corrected --> reading
  accepted --> route
  route -->|One part or already connected| action
  route -->|Not connected yet| plan
  plan --> planYes
  planYes --> action
  action --> checked
  checked --> deny
  checked --> once
  checked --> always
  once --> scenario
  always --> scenario
  scenario --> result
  result --> good
  result --> blockedRelease
  blockedRelease --> failOk
  good --> choose
  failOk --> choose
  choose --> notes
  notes --> ship
  ship --> stays
Loading

She does not choose the architecture. The product shows either the action or the plan. She accepts a reading, a plan, an action, a scenario, a result, or a failure. The original reading is unchanged by a failure acceptance.

Workflow

flowchart TD
  task[A task arrives]
  same{Is --with the same role?}
  refused[Exit before any model call. Nothing is stored]
  gate{What is already accepted?}
  one[One named service: that role works. No lead]
  hand[Connection spec names the roles: they hand off. The lead is absent]
  cross[Named services or modules, and no connection exists]
  moduleLead[Module lead writes a plan of depth at most 2]
  productLead[Product lead writes a plan of depth at most 2]
  person[The person accepts the plan. It is binding]
  readingStop[Person accepts or corrects the reading. No Allow or Deny]
  early[Code, scenario, or release with no accepted spec]
  noChoice[Stop. No Allow or Deny]
  branch[A branch starts only after its prerequisites have results]
  quiet{Two rounds with no progress?}
  hold[Stop for the person]
  again[They accept one new plan. Finished decisions stay]
  noAgain[A second rebuild does not start]
  artifact[The owner returns an artifact id and a summary]
  guard[Spec accept, QA write, release, sdd next, sdd complete, and createChange are rejected]
  need{Check the draft against an accepted spec?}
  critic[A different role critiques. The runner checks the ids. At most 3 passes]
  show[Stop names one action, in their words]
  deny[Deny applies nothing]
  once[Allow once runs only that named action]
  always[Always allow saves the same tool and the same inputs]
  ask[Ask first stays stopped]

  task --> same
  same -->|Yes| refused
  same -->|No| gate
  gate -->|One named service| one
  gate -->|Connection already accepted| hand
  gate -->|Cross-scope, no connection| cross
  gate -->|A reading, no spec yet| readingStop
  gate -->|Code, scenario, or release, no spec| early
  cross -->|Inside one module| moduleLead
  cross -->|Across modules| productLead
  moduleLead --> person
  productLead --> person
  person --> branch
  branch --> quiet
  quiet -->|Yes, first time| hold
  hold --> again
  again --> branch
  quiet -->|Yes, already rebuilt| noAgain
  quiet -->|No| artifact
  one --> guard
  hand --> guard
  artifact --> guard
  guard --> need
  need -->|Yes| critic
  need -->|No| show
  critic --> show
  early --> noChoice
  show --> deny
  show --> once
  show --> always
  show --> ask
Loading

A child that is still open leaves the parent open. The lead stores the artifact id and the summary, not the specialist's transcript. Other specs keep their decision ids when a connection is accepted. Frontend and backend are not a cross-scope task unless the spec names them as separate services.

Cross-scope work

The hierarchy is the work. A role binds to one scope: a service, a module, or the product. A module lead exists only when that module has more than one service. A product lead exists only when the product has more than one module. The lead plans and names the next owner. It does not take the specialist's tools or memory.

  1. An accepted spec covers one named service. That role runs. Frontend and backend alone do not create this split.
  2. An accepted connection spec names the owners. They hand off. The lead is not on that path. A connection between two services is the same kind of spec as a connection between two modules.
  3. The task crosses scopes and no connection exists. The lead writes a tree of depth at most 2. Each node has a scope, an owner, prerequisite decision ids, the artifact, and that owner's approval boundary. The person accepts the plan before anyone writes.

The papers behind this shape are Cemri et al., arXiv:2503.13657 (weak checks and ignored roles), Fourney et al., arXiv:2411.04468 (task ledger and progress ledger), Anthropic's multi-agent research write-up of 13 Jun 2025 (separate contexts, artifact by reference), Deng et al., arXiv:2610.22195 (expand a branch only after its prerequisites return), and arXiv:2610.19342 (a peer is not trusted unless the protocol checks, and a handoff must not drop the approval gate).

Sharing

The person can share a role template with the team. The template has the job, description, skills, routines, and boundary. It does not include the conversation, memory, tool logins, or secrets. Adding it creates a new copy.

There is no hosted team chat in this issue. The team already talks in Slack or Teams. A role file in the repo can be copied to another clone of the same product. A tool that needs a sign-in uses the account of the person who started the run.

Acceptance

  • sdd role is implemented in this repo, core plus a thin CLI command. sdd agents install still only installs a host stub. The runner does not call createChange.
  • No connector reads or posts on X. A task that names X is refused.
  • Hide leaves routines running. Duplicate leaves the conversation and memory behind.
  • Stop now ends the turn and leaves a completed action in place.
  • A handoff wakes the other role, and both conversations show the spec or tool record. With messaging off, it does not send.
  • --with the same role makes no model call and writes no record. A review uses a separate call, the runner checks ids, a bad cite spends the pass, and pass 4 does not start.
  • Code, a scenario, or a release with no accepted spec stops before a draft and offers no Allow or Deny. A first reading can be drafted and does not accept the spec.
  • Ask first wins over always-allow. The runner matches the tool and the inputs. An unattended approval expires at 10 minutes and does not run.
  • Spec accept, replace, QA write, generate release, sdd next, sdd complete, and createChange are rejected before they run, including through GitHub, GitLab, Jenkins, JFrog, Jira, Slack, or Teams. A commit, push, tag, or pull request runs only when the stop names it.
  • A Jenkins or GitHub Actions failure can be read inside the boundary. Merging a pull request, deploying, or promoting a JFrog artifact stops for approval.
  • A missing Jira, Aha, Asana, or Azure DevOps record is reported and not invented. A Slack or Teams draft is not posted until the person sends it.
  • A routine refuses to invent a pipeline result when the source is missing, and it cannot write a QA result.
  • One accepted service runs that role and creates no lead. An accepted connection hands off with the lead absent and leaves other decision ids unchanged.
  • A cross-scope task with no connection waits for the person to accept the plan. A branch waits for its prerequisites. The parent waits for every child. A second rebuild does not start without a new accepted plan.
  • The lead's record has the artifact id and a summary, not the specialist's transcript.

Out of scope

A clone of Grok Bot. A second repository. Social networks, posting or reading X, voice chat, and a general-purpose assistant. Replacing Jira, Jenkins, or GitHub as the place where stage progress is stored. An inbound MCP server. A hosted multi-tenant studio. Do not start F-001 from this issue. Do not fold this into the search epic (#21–#26).

Development order

  1. sdd role create and sdd role run in packages/core and packages/cli. Role file, plain-language stop, Allow once, Always allow, Deny, Ask first, and the accuracy loop. No page. No connectors.
  2. Handoff and the task network for services and modules the person has named, inside one sdd root.
  3. Outbound connectors and routines. Slack and Teams drafts stay unsent until the person sends them. Trackers seed a change or report status. They do not store stage progress.

Spec follow-up

Updating feat/aidlc-greenfield does not block slice 1. When that branch is next edited, point F-015 at free-form handoff only, and add named services, the task network, and the connectors above. A connection between two named services is the same kind of spec as F-018.

Activity

  1. changed the title [-]CLI role agents: accuracy loop by handoff, not one-shot generation[/-] [+]Role agents replicate Grok Bot[/+] on Oct 18, 2026
  2. changed the title [-]Role agents replicate Grok Bot[/-] [+]Role agents for spec-driven software development[/+] on Oct 18, 2026
  3. added
    approved-for-developmentContent reviewed and approved to develop. The issue stays open.
    epicLarge body of work delivered through later issues
    on Oct 18, 2026
  4. harsha09 commented on Oct 19, 2026

    @harsha09
    OwnerAuthor

    Slice 1 is on main in #43 (merge aecf412).

    sdd role create and sdd role run are in. That covers the role file, the plain-language stop, Allow once, Always allow, Deny, Ask first, and the accuracy loop. Allow once writes only the named file. Commit, push, tag, pull request, merge, and deploy stay stopped in this slice.

    This epic stays open. The page and the connectors are still to do.

  5. harsha09 commented on Oct 19, 2026

    @harsha09
    OwnerAuthor

    Three follow-up stories from this epic are on main. Issue #37 stays open.

    The handoff and task-network slice, and the connectors slice, are not in these pulls.

  6. harsha09 commented on Oct 19, 2026

    @harsha09
    OwnerAuthor

    Slice 2 shipped in #52 (a50ab7b): handoff and the task network. A role can hand an accepted section to its owner, and a lead plan stays pending until it is accepted.

    Issue #37 stays open. Connectors and routines are still later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    approved-for-developmentContent reviewed and approved to develop. The issue stays open.enhancementNew feature or requestepicLarge body of work delivered through later issues

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions