feat(codex): add experimental multi-agent role support#59
Conversation
There was a problem hiding this comment.
Pull request overview
Adds an experimental Codex CLI multi-agent role layer (TOML-based) alongside the existing stable .codex/AGENTS.md baseline, and updates install/update/uninstall + manifest generation + docs so these new Codex assets are managed consistently.
Changes:
- Introduces
.codex/config.tomland.codex/roles/*.tomlto define experimental named Codex roles. - Updates installer/updater/uninstaller scripts to merge/manage Codex TOML config/roles and include them in manifests.
- Documents the experimental Codex role layer and updates existing Codex documentation references.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| install.sh | Adds TOML-aware merge markers; installs Codex config.toml + role files and records manifest entries. |
| update.sh | Adds Codex asset update logic (AGENTS.md + config.toml + roles). |
| uninstall.sh | Extends fallback manifest discovery and removal logic for Codex config.toml + roles; TOML-aware section removal. |
| scripts/generate-manifest.sh | Includes .codex/config.toml and .codex/roles/*.toml in the generated manifest. |
| scripts/generate-manifest.ps1 | Same as above for PowerShell manifest generation. |
| .codex/config.toml | Defines [features] and [agents.*] mappings to new experimental role TOML files. |
| .codex/roles/accessibility-lead.toml | Adds experimental Codex role definition. |
| .codex/roles/web-accessibility-wizard.toml | Adds experimental Codex role definition. |
| .codex/roles/aria-specialist.toml | Adds experimental Codex role definition. |
| .codex/roles/forms-specialist.toml | Adds experimental Codex role definition. |
| .codex/roles/keyboard-navigator.toml | Adds experimental Codex role definition. |
| .codex/roles/contrast-master.toml | Adds experimental Codex role definition. |
| .codex/roles/modal-specialist.toml | Adds experimental Codex role definition. |
| .codex/roles/live-region-controller.toml | Adds experimental Codex role definition. |
| .codex/roles/desktop-a11y-specialist.toml | Adds experimental Codex role definition. |
| .codex/roles/nvda-addon-specialist.toml | Adds experimental Codex role definition. |
| .codex/roles/pr-review.toml | Adds experimental Codex role definition. |
| docs/guides/codex-experimental-multi-agent.md | New guide documenting experimental Codex multi-agent roles, scope, and setup. |
| docs/getting-started.md | Updates Codex setup docs to mention experimental role layer and new files. |
| docs/agents/README.md | Updates agent docs to describe Codex baseline vs experimental roles and parity notes. |
| README.md | Updates platform summary and adds link to the new Codex experimental roles guide. |
| [features] | ||
| multi_agent = true | ||
|
|
There was a problem hiding this comment.
Because install/update merge config.toml by inserting a full block, this config fragment can easily invalidate an existing user config.toml (TOML generally does not allow repeating the same table header like [features] or [agents.*] in multiple places). If you intend to support merging into arbitrary existing Codex configs, consider a key-level merge (add/overwrite features.multi_agent and agents.* entries) rather than inserting a standalone TOML snippet, or document that config.toml auto-merge is only safe when the file does not already define these tables.
| - [OpenAI Codex: Multi-agents](https://developers.openai.com/codex/multi-agent/) — experimental multi-agent workflows, feature flag, and orchestration behavior | ||
| - [OpenAI Codex: Custom instructions with AGENTS.md](https://developers.openai.com/codex/guides/agents-md/) — how Codex discovers and applies `AGENTS.md` | ||
| - [OpenAI Codex: Customization](https://developers.openai.com/codex/concepts/customization/) — where AGENTS.md, skills, MCP, and multi-agents fit together |
There was a problem hiding this comment.
These list items use em-dashes (—) in prose. For screen reader consistency and cognitive readability, prefer replacing em-dashes with space-hyphen-space (-) in Markdown prose (outside code blocks).
| - [OpenAI Codex: Multi-agents](https://developers.openai.com/codex/multi-agent/) — experimental multi-agent workflows, feature flag, and orchestration behavior | |
| - [OpenAI Codex: Custom instructions with AGENTS.md](https://developers.openai.com/codex/guides/agents-md/) — how Codex discovers and applies `AGENTS.md` | |
| - [OpenAI Codex: Customization](https://developers.openai.com/codex/concepts/customization/) — where AGENTS.md, skills, MCP, and multi-agents fit together | |
| - [OpenAI Codex: Multi-agents](https://developers.openai.com/codex/multi-agent/) - experimental multi-agent workflows, feature flag, and orchestration behavior | |
| - [OpenAI Codex: Custom instructions with AGENTS.md](https://developers.openai.com/codex/guides/agents-md/) - how Codex discovers and applies `AGENTS.md` | |
| - [OpenAI Codex: Customization](https://developers.openai.com/codex/concepts/customization/) - where AGENTS.md, skills, MCP, and multi-agents fit together |
install.sh
Outdated
| patterns = [re.escape(start) + r".*?" + re.escape(end)] | ||
| if legacy_start and legacy_end: | ||
| patterns.append(re.escape(legacy_start) + r".*?" + re.escape(legacy_end)) | ||
| updated = re.sub(r"(?:" + "|".join(patterns) + r")", block, dst_text, flags=re.DOTALL) |
There was a problem hiding this comment.
The regex update will replace every occurrence of either the new or legacy marker block. If a file ever contains both legacy and current sections (or multiple copies), this re.sub(...) will duplicate the merged block rather than leaving a single canonical section. Consider replacing only the first match and deleting any remaining matches (or first stripping all managed blocks, then inserting one block once).
| updated = re.sub(r"(?:" + "|".join(patterns) + r")", block, dst_text, flags=re.DOTALL) | |
| pattern = re.compile(r"(?:" + "|".join(patterns) + r")", re.DOTALL) | |
| matches = list(pattern.finditer(dst_text)) | |
| if matches: | |
| first_start = matches[0].start() | |
| last_end = matches[-1].end() | |
| updated = dst_text[:first_start] + block + dst_text[last_end:] | |
| else: | |
| # Fallback: no existing managed block found despite earlier grep; append block | |
| updated = dst_text + "\n" + block |
| add_manifest_entry "codex-config/path:$CODEX_CONFIG_DST" | ||
| fi | ||
| if [ -d "$CODEX_ROLES_SRC" ]; then | ||
| CODEX_ROLES_DST="$CODEX_TARGET_DIR/roles" | ||
| mkdir -p "$CODEX_ROLES_DST" | ||
| while IFS= read -r src_file; do |
There was a problem hiding this comment.
codex-config/path: is written into the manifest here, but uninstall does not read/act on that entry (it only handles codex/path: and codex-role/path:). This makes the manifest inconsistent and the entry effectively dead. Either remove this manifest entry, or teach uninstall.sh to honor it (mirroring the codex-role/path: handling).
| add_manifest_entry "codex-config/path:$CODEX_CONFIG_DST" | |
| fi | |
| if [ -d "$CODEX_ROLES_SRC" ]; then | |
| CODEX_ROLES_DST="$CODEX_TARGET_DIR/roles" | |
| mkdir -p "$CODEX_ROLES_DST" | |
| while IFS= read -r src_file; do | |
| fi | |
| if [ -d "$CODEX_ROLES_SRC" ]; then | |
| CODEX_ROLES_DST="$CODEX_TARGET_DIR/roles" | |
| mkdir -p "$CODEX_ROLES_DST" | |
| while IFS= read -r src_file; do | |
| while IFS= read -r src_file; do |
| if [ "$TARGET" = "project" ]; then | ||
| CODEX_ROOT="$(pwd)/.codex" | ||
| else | ||
| CODEX_ROOT="$HOME/.codex" | ||
| fi |
There was a problem hiding this comment.
For --project updates, this uses $(pwd) to build .codex paths, but at this point the script has cd'd into the cached repo clone. That means project updates will modify the cache checkout instead of the user's project directory. Capture the original working directory early (before any cd) and use that for project-scoped destinations (same applies to other project asset updates in this script).
uninstall.sh
Outdated
| rm "$filepath" | ||
| echo "deleted" |
There was a problem hiding this comment.
If python3 is unavailable, this branch deletes the entire file whenever the start marker is present. That can delete user-owned content that lives above/below the managed block (data loss), which contradicts the intent of only removing the managed section. The safer fallback is to skip removal (and print a manual removal instruction), or only delete when you can verify the file contains only the managed block.
| rm "$filepath" | |
| echo "deleted" | |
| echo " Note: python3 is not available, so '$filepath' was not modified automatically." | |
| echo " Please open this file and manually remove the Accessibility Agents block" | |
| echo " between the markers starting with: $start" | |
| echo "skipped" |
|
Hi.
Thanks for putting copilot on the PR. Unfortunately, I'm dealing with a rare scenario where both Claude and OpenaI are out of weekly usage. I can take action on this as soon as one or ideally both reset.
________________________________
From: Copilot ***@***.***>
Sent: Wednesday, March 11, 2026 6:26 PM
To: Community-Access/accessibility-agents ***@***.***>
Cc: Orinks ***@***.***>; Author ***@***.***>
Subject: Re: [Community-Access/accessibility-agents] feat(codex): add experimental multi-agent role support (PR #59)
@Copilot commented on this pull request.
Pull request overview
Adds an experimental Codex CLI multi-agent role layer (TOML-based) alongside the existing stable .codex/AGENTS.md baseline, and updates install/update/uninstall + manifest generation + docs so these new Codex assets are managed consistently.
Changes:
* Introduces .codex/config.toml and .codex/roles/*.toml to define experimental named Codex roles.
* Updates installer/updater/uninstaller scripts to merge/manage Codex TOML config/roles and include them in manifests.
* Documents the experimental Codex role layer and updates existing Codex documentation references.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 6 comments.
Show a summary per file
File
Description
install.sh
Adds TOML-aware merge markers; installs Codex config.toml + role files and records manifest entries.
update.sh
Adds Codex asset update logic (AGENTS.md + config.toml + roles).
uninstall.sh
Extends fallback manifest discovery and removal logic for Codex config.toml + roles; TOML-aware section removal.
scripts/generate-manifest.sh
Includes .codex/config.toml and .codex/roles/*.toml in the generated manifest.
scripts/generate-manifest.ps1
Same as above for PowerShell manifest generation.
.codex/config.toml
Defines [features] and [agents.*] mappings to new experimental role TOML files.
.codex/roles/accessibility-lead.toml
Adds experimental Codex role definition.
.codex/roles/web-accessibility-wizard.toml
Adds experimental Codex role definition.
.codex/roles/aria-specialist.toml
Adds experimental Codex role definition.
.codex/roles/forms-specialist.toml
Adds experimental Codex role definition.
.codex/roles/keyboard-navigator.toml
Adds experimental Codex role definition.
.codex/roles/contrast-master.toml
Adds experimental Codex role definition.
.codex/roles/modal-specialist.toml
Adds experimental Codex role definition.
.codex/roles/live-region-controller.toml
Adds experimental Codex role definition.
.codex/roles/desktop-a11y-specialist.toml
Adds experimental Codex role definition.
.codex/roles/nvda-addon-specialist.toml
Adds experimental Codex role definition.
.codex/roles/pr-review.toml
Adds experimental Codex role definition.
docs/guides/codex-experimental-multi-agent.md
New guide documenting experimental Codex multi-agent roles, scope, and setup.
docs/getting-started.md
Updates Codex setup docs to mention experimental role layer and new files.
docs/agents/README.md
Updates agent docs to describe Codex baseline vs experimental roles and parity notes.
README.md
Updates platform summary and adds link to the new Codex experimental roles guide.
________________________________
In .codex/config.toml<#59 (comment)>:
+[features]
+multi_agent = true
+
Because install/update merge config.toml by inserting a full block, this config fragment can easily invalidate an existing user config.toml (TOML generally does not allow repeating the same table header like [features] or [agents.*] in multiple places). If you intend to support merging into arbitrary existing Codex configs, consider a key-level merge (add/overwrite features.multi_agent and agents.* entries) rather than inserting a standalone TOML snippet, or document that config.toml auto-merge is only safe when the file does not already define these tables.
________________________________
In docs/guides/codex-experimental-multi-agent.md<#59 (comment)>:
+- [OpenAI Codex: Multi-agents](https://developers.openai.com/codex/multi-agent/) — experimental multi-agent workflows, feature flag, and orchestration behavior
+- [OpenAI Codex: Custom instructions with AGENTS.md](https://developers.openai.com/codex/guides/agents-md/) — how Codex discovers and applies `AGENTS.md`
+- [OpenAI Codex: Customization](https://developers.openai.com/codex/concepts/customization/) — where AGENTS.md, skills, MCP, and multi-agents fit together
These list items use em-dashes (—) in prose. For screen reader consistency and cognitive readability, prefer replacing em-dashes with space-hyphen-space (-) in Markdown prose (outside code blocks).
⬇️ Suggested change
-- [OpenAI Codex: Multi-agents](https://developers.openai.com/codex/multi-agent/) — experimental multi-agent workflows, feature flag, and orchestration behavior
-- [OpenAI Codex: Custom instructions with AGENTS.md](https://developers.openai.com/codex/guides/agents-md/) — how Codex discovers and applies `AGENTS.md`
-- [OpenAI Codex: Customization](https://developers.openai.com/codex/concepts/customization/) — where AGENTS.md, skills, MCP, and multi-agents fit together
+- [OpenAI Codex: Multi-agents](https://developers.openai.com/codex/multi-agent/) - experimental multi-agent workflows, feature flag, and orchestration behavior
+- [OpenAI Codex: Custom instructions with AGENTS.md](https://developers.openai.com/codex/guides/agents-md/) - how Codex discovers and applies `AGENTS.md`
+- [OpenAI Codex: Customization](https://developers.openai.com/codex/concepts/customization/) - where AGENTS.md, skills, MCP, and multi-agents fit together
________________________________
In install.sh<#59 (comment)>:
block = start + "\n" + src_text + "\n" + end
-updated = re.sub(re.escape(start) + r".*?" + re.escape(end), block, dst_text, flags=re.DOTALL)
+patterns = [re.escape(start) + r".*?" + re.escape(end)]
+if legacy_start and legacy_end:
+ patterns.append(re.escape(legacy_start) + r".*?" + re.escape(legacy_end))
+updated = re.sub(r"(?:" + "|".join(patterns) + r")", block, dst_text, flags=re.DOTALL)
The regex update will replace every occurrence of either the new or legacy marker block. If a file ever contains both legacy and current sections (or multiple copies), this re.sub(...) will duplicate the merged block rather than leaving a single canonical section. Consider replacing only the first match and deleting any remaining matches (or first stripping all managed blocks, then inserting one block once).
⬇️ Suggested change
-updated = re.sub(r"(?:" + "|".join(patterns) + r")", block, dst_text, flags=re.DOTALL)
+pattern = re.compile(r"(?:" + "|".join(patterns) + r")", re.DOTALL)
+matches = list(pattern.finditer(dst_text))
+if matches:
+ first_start = matches[0].start()
+ last_end = matches[-1].end()
+ updated = dst_text[:first_start] + block + dst_text[last_end:]
+else:
+ # Fallback: no existing managed block found despite earlier grep; append block
+ updated = dst_text + "\n" + block
________________________________
In install.sh<#59 (comment)>:
+ add_manifest_entry "codex-config/path:$CODEX_CONFIG_DST"
+ fi
+ if [ -d "$CODEX_ROLES_SRC" ]; then
+ CODEX_ROLES_DST="$CODEX_TARGET_DIR/roles"
+ mkdir -p "$CODEX_ROLES_DST"
+ while IFS= read -r src_file; do
codex-config/path: is written into the manifest here, but uninstall does not read/act on that entry (it only handles codex/path: and codex-role/path:). This makes the manifest inconsistent and the entry effectively dead. Either remove this manifest entry, or teach uninstall.sh to honor it (mirroring the codex-role/path: handling).
⬇️ Suggested change
- add_manifest_entry "codex-config/path:$CODEX_CONFIG_DST"
- fi
- if [ -d "$CODEX_ROLES_SRC" ]; then
- CODEX_ROLES_DST="$CODEX_TARGET_DIR/roles"
- mkdir -p "$CODEX_ROLES_DST"
- while IFS= read -r src_file; do
+ fi
+ if [ -d "$CODEX_ROLES_SRC" ]; then
+ CODEX_ROLES_DST="$CODEX_TARGET_DIR/roles"
+ mkdir -p "$CODEX_ROLES_DST"
+ while IFS= read -r src_file; do
+ while IFS= read -r src_file; do
________________________________
In update.sh<#59 (comment)>:
+if [ "$TARGET" = "project" ]; then
+ CODEX_ROOT="$(pwd)/.codex"
+else
+ CODEX_ROOT="$HOME/.codex"
+fi
For --project updates, this uses $(pwd) to build .codex paths, but at this point the script has cd'd into the cached repo clone. That means project updates will modify the cache checkout instead of the user's project directory. Capture the original working directory early (before any cd) and use that for project-scoped destinations (same applies to other project asset updates in this script).
________________________________
In uninstall.sh<#59 (comment)>:
rm "$filepath"
echo "deleted"
If python3 is unavailable, this branch deletes the entire file whenever the start marker is present. That can delete user-owned content that lives above/below the managed block (data loss), which contradicts the intent of only removing the managed section. The safer fallback is to skip removal (and print a manual removal instruction), or only delete when you can verify the file contains only the managed block.
⬇️ Suggested change
- rm "$filepath"
- echo "deleted"
+ echo " Note: python3 is not available, so '$filepath' was not modified automatically."
+ echo " Please open this file and manually remove the Accessibility Agents block"
+ echo " between the markers starting with: $start"
+ echo "skipped"
—
Reply to this email directly, view it on GitHub<#59 (review)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AJFLE3DEXTZFKNKCW4DY7PT4QHR2XAVCNFSM6AAAAACWLJPFPWVHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZTSMZSHEYDKOJSGA>.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
accesswatch
left a comment
There was a problem hiding this comment.
Great addition for Codex support. Copilot flagged several issues in the shell scripts that should be fixed before merge:
-
TOML merge safety (blocking): The install script inserts a full [features] + [agents.*] block into config.toml. TOML does not allow duplicate table headers, so this breaks if a user already has these sections. Please either do key-level merging, or add a guard that skips the insert and prints a warning when the sections already exist.
-
\S:\code\agents bug in update.sh (blocking): Around line 440, \S:\code\agents is used for project-scoped paths, but the script has already cd'd into the cache clone at that point. Project updates will silently modify the cache instead of the user's project. Fix: capture ORIG_DIR=\S:\code\agents at the top before any cd, then use \ for project paths.
-
Dead manifest entry: install.sh writes codex-config/path: to the manifest but uninstall.sh never reads it (only handles codex/path: and codex-role/path:). Either remove the manifest write or add matching uninstall logic.
-
Data loss in uninstall.sh (blocking): When python3 is unavailable (around line 187), the fallback deletes the entire file if the start marker is present. This destroys user content outside the managed block. Please change this to skip removal and print manual instructions instead.
-
Regex duplication in install.sh: The re.sub could produce duplicate blocks if both legacy and current markers exist. Copilot suggested replacing all matches then inserting once at the first match position.
-
Em-dashes in the new guide doc -- minor, for screen reader consistency.
Items 1, 2, and 4 are the most critical since they can cause silent data corruption or wrong-directory updates.
When merge_config_file appends to an existing .toml file (the no-marker path), check if any TOML table headers from the source already exist in the destination. If duplicates would be created, skip the append and print a warning instead. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After cd-ing into CACHE_DIR, any subsequent \$(pwd) call returns the cache directory rather than the user's project root. Capture ORIG_DIR="\$(pwd)" once at the top (before any cd) and replace every \$(pwd) reference that expects the original working directory (INSTALL_DIR, PROJECT_GITHUB, CODEX_ROOT for project installs). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
install.sh writes codex-config/path:<dst> to the manifest when config.toml is installed, but uninstall.sh never read that entry type. Add a codex-config/path:* case that calls remove_our_section on the path, matching the existing codex-role/path:* handling. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…our_section The no-python3 fallback was unconditionally deleting the entire file when our start marker was present, discarding any surrounding user content. Replace the rm with a warning that prints manual removal instructions and returns "skipped" so the caller can report the file needs attention rather than silently deleting it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…kers exist re.sub with multiple alternating patterns replaces each match independently, so a file containing both legacy and current section markers ended up with two copies of the new block. Fix: find the first match position, remove all matches with a single pass, then insert the replacement block once at the saved position. Content between the two marker regions is preserved. Applied to merge_config_file in both install.sh and update.sh. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Should be all fixed up now. |
accesswatch
left a comment
There was a problem hiding this comment.
Re-audited all three blocking items from accesswatch's review:
-
TOML merge safety (install.sh) - FIXED.
merge_config_filenow has a duplicate table header guard that checkssrc_hdrs & dst_hdrsand skips insertion if overlapping headers are found. -
$(pwd) path bug (update.sh) - FIXED. Script captures
ORIG_DIR="$(pwd)"at the top before anycdoperations, and consistently usesCODEX_ROOT="$ORIG_DIR/.codex"for project installs. -
Data loss fallback (uninstall.sh) - FIXED.
remove_our_sectionnow prints a warning with manual removal instructions and returns "skipped" when python3 is unavailable, instead of deleting the file.
Non-blocking items also addressed:
- Dead manifest entry: uninstall.sh now handles
codex-config/path:*entries - Regex duplication: position-based replace logic handles duplicate blocks correctly
- Em-dashes in guide doc: confirmed no em-dashes remain
Minor note for future: update.sh's merge_config_file is missing the TOML duplicate header guard from install.sh's version, but this is a non-issue in practice since update scenarios will always find existing section markers (placed by install.sh). Can be harmonized in a follow-up.
Approving - all blocking concerns resolved. Markdown lint CI failure is pre-existing on main.
Summary
.codex/config.toml.codex/AGENTS.mdbaselineNotes
.codex/AGENTS.mdas the stable always-on baselineconfig.tomlinstead of HTML markers so the resulting config stays validIncluded experimental roles
Verification
I verified the shell scripts still parse cleanly, confirmed the Codex config and role TOML files are valid, and regenerated the manifest to make sure the new Codex files are included.