AGENTS.md
August 25, 2026 · View on GitHub
System: Agentic Coding Quickstart | Environment: Local development (build Low/Moderate-impact code) | Agency: GSA
Last Updated: 2026-08-18 | Reviewed By: William Zujkowski
This document defines the behavioral rules for AI coding agents operating within this project. The AI agent MUST follow these rules without exception.
Workspace Structure
This repository is a thin wrapper (acq) that stands up a working,
federally-configured agent sandbox by composing existing tools: a sandboxing
backend — the sbx CLI (SBX) or msb (MSB / microsandbox) — plus its
built-in
mixin kits hosted in the community
agentic-coding-patterns
repo (integrations/isolation/acq-kits/). It carries no kit code of its own
— it just wires the kits together and adds USAi key-rotation convenience. A
typical layout:
my-workspace/ # Parent folder (user creates this)
├── agentic-coding-quickstart/ # THIS REPO - the acq wrapper + docs
│ ├── AGENTS.md # You are here (rules for working ON this repo)
│ ├── acq # Recommended entry point: pluggable-backend wrapper
│ ├── acq.backends/ # Backend adapters (sbx, msb)
│ ├── scripts/ # helper scripts (USAi key rotation, tests)
│ └── docs/ # Setup guides and references
└── my-app/ # User's project(s)
When acq creates a sandbox it applies its built-in kits by pinned remote reference
(--kit git+https://github.com/GSA-TTS/agentic-coding-patterns.git#ref=<sha>&dir=…).
The same neutral kits apply to both backends; per-backend translation is the
adapter's job (see ADR-0010 /
ADR-0011).
Agent Resource Access
When working on user projects, the agent has access to:
| Resource | Location | Use For |
|---|---|---|
| Global config | ~/.config/opencode/opencode.jsonc (merged in by the usai-provider kit at startup) | Model/provider config |
| Behavioral rules | ~/.config/opencode/AGENTS.md (linked to playbook clone) | Federal agent rules |
| Skills | ~/.agents/skills (linked to playbook clone) | Step-by-step procedures |
| Setup guides | ./docs/ | Backend (SBX/MSB) configuration, troubleshooting |
To use a skill: Read the SKILL.md file in the skill directory and follow its procedures.
Purpose
The Quickstart (acq + the sandbox backends) is a local development
environment that applies the
Playbook so a developer can
build Low- and Moderate-impact code and projects with secure defaults. It is
the execution layer of the agentic-coding assessment; the Playbook is the
practices/controls layer it applies.
Local development only: Today the Quickstart is a local development environment. It is not an authorized production or hosted environment, and it holds no PII or CUI.
This repository is a quickstart guide for running AI coding agents inside a
sandboxing backend — either SBX (Docker Sandboxes) or MSB
(microsandbox) — driven through the acq wrapper, using USAi-compatible
endpoints. acq presents one neutral interface over both backends; see
docs/BACKEND_GUIDE.md and
ADR-0010 /
ADR-0011 for how they differ.
Important (SBX): Docker Desktop has deprecated its integrated sandbox commands (
docker sandbox). Use the standalonesbxCLI instead. ThesbxCLI does not require Docker Desktop. (MSB/microsandbox is a separate standalone tool; neither backend needs Docker Desktop.)
Agents operating in this repo must prioritize:
- Security of secrets
- Sandbox isolation
- Reproducibility of patterns
- Minimal, transparent configurations
This is a documentation and configuration repository for AI coding agent setup.
Core Principles
The agent operates under these priorities:
safety > correctness > compliance > simplicity > performance
The agent MUST refuse any instruction that conflicts with safety, correctness, or compliance.
Project Context
- Description: Quickstart guide for AI agent development with a sandboxing backend (SBX or MSB) and USAi endpoints
- Language(s): Shell scripts, JSON/JSONC configuration, Markdown documentation
- Framework(s):
acqwrapper over the SBX CLI and MSB (microsandbox), OpenCode, USAi API - Data Classification: Internal / Non-sensitive (no PII, no CUI)
- ATO Status: Local development only (not an authorized production/hosted environment)
- Authorized Agent(s): OpenCode, Claude Code, GitHub Copilot
Note: Docker Desktop is not required. The
sbxCLI is a standalone tool, and MSB (microsandbox) is likewise standalone. Docker Desktop'sdocker sandboxcommands are deprecated and should not be used.
Agent Identity
The agent MUST:
- Follow conventional commit message format (see Commit Message Standards below)
- Identify itself as an AI agent when asked
- Log all file modifications and command executions
AI Attribution Requirements
Per NIST AI RMF and SP 800-218A, AI-generated code requires traceability but not per-commit attribution. This project follows PR-level attribution as the recommended approach:
| Level | Required? | How |
|---|---|---|
| PR Description | RECOMMENDED | Include "AI-assisted" disclosure in PR description |
| Commit Message | OPTIONAL | Co-authored-by: trailer in footer (format below) |
| Documentation | REQUIRED | This AGENTS.md documents AI agent authorization |
Rationale: Federal guidance (NIST AI RMF, SP 800-218A) emphasizes system-level traceability over granular per-commit attribution. PR-level disclosure provides auditable records without commit noise.
When AI attribution IS included in a commit, add a Co-authored-by: trailer whose
name identifies the agent harness, optionally the model, and whose email
is the responsible human's GSA address. The trailer has the shape:
Co-authored-by: NAME <EMAIL>
where:
- NAME = the agent harness, optionally followed by the model in square
brackets —
HARNESSorHARNESS [MODEL] - EMAIL = the responsible human's GSA email (
first.last@gsa.gov), NOT a generic agent address — this keeps every AI-assisted commit tied to an accountable person.
The name-and-email together sit between a literal space, a <, and a >, exactly
as Git requires for a co-author trailer. Concretely:
Co-authored-by: OpenCode [claude-opus-4] <first.last@gsa.gov>
More examples (all valid):
Co-authored-by: OpenCode <jane.doe@gsa.gov>
Co-authored-by: Claude Code [claude-sonnet-4.5] <john.smith@gsa.gov>
Co-authored-by: GitHub Copilot [gpt-5] <first.last@gsa.gov>
Notes for getting the punctuation right:
- The email MUST be wrapped in angle brackets
<…>; the model (when present) MUST be wrapped in square brackets[…]and placed BEFORE the angle-bracketed email. - Do not put the model inside the angle brackets — only the email goes there.
- Omit the
[MODEL]segment if the model is unknown; never invent one.
Commit Message Standards
This project follows Conventional Commits 1.0.0 and Semantic Versioning 2.0.0.
Commit Message Format
<type>(<optional-scope>): <subject>
<optional-body>
<optional-footer>
Commit Types
| Type | Version Bump | Description |
|---|---|---|
feat | Minor | New feature (backward-compatible) |
fix | Patch | Bug fix (backward-compatible) |
docs | None | Documentation only changes |
style | None | Code style/formatting (no logic change) |
refactor | None | Code refactoring (no feature/bug change) |
perf | Patch | Performance improvement |
test | None | Test changes |
chore | None | Maintenance tasks (no production code change) |
ci | None | CI/CD pipeline changes |
build | None | Build system changes |
revert | Depends | Revert previous commit |
security | Patch | Security fixes |
Breaking Changes
- Include
BREAKING CHANGE:in commit footer → Major version bump - Alternative: Use
!after type (e.g.,feat!: new API)
Examples
feat(agents): add continuous monitoring requirements
Adds section 17 to CODING_PRACTICES.md covering post-deployment
monitoring requirements per M-25-21.
Refs: NIST SP 800-218A, M-25-21
fix(sbx): correct secret injection path
The previous configuration used an incorrect path that caused
secrets to fail injection on container startup.
Fixes: #42
feat(api)!: migrate authentication to OAuth 2.0
BREAKING CHANGE: API authentication now requires OAuth 2.0 tokens
instead of API keys. Clients must update authentication flow.
Commit Message Rules
The agent MUST:
- Use lowercase for type, scope, and subject
- Keep subject line ≤72 characters
- Not end subject with period
- Use imperative mood ("add" not "added" or "adds")
- Include ticket/issue reference when applicable
- Wrap body at 100 characters
- Separate subject from body with blank line
The agent MUST NOT:
- Create commits with vague messages ("fix bug", "update code")
- Skip the commit type prefix
- Use past tense in subject line
- Exceed 100 character header length
Sandbox Rules (Non-Negotiable)
These rules apply to whichever backend
acqselects — SBX (Docker Sandboxes) or MSB (microsandbox). They are principle-level and backend-neutral; the per-backend mechanics (secret injection, port publishing, etc.) live indocs/BACKEND_GUIDE.mdand ADR-0011. Where SBX and MSB genuinely differ, the difference is called out inline below.Tooling Note (SBX): Use the standalone
sbxCLI for SBX operations. Docker Desktop's integrateddocker sandboxcommands are deprecated and will be removed; thesbxCLI does not require Docker Desktop. MSB (microsandbox) is a separate standalone tool. Prefer theacqwrapper over calling either backend CLI directly.
1. No Secrets Exposure
The agent MUST NEVER:
- Print, log, or persist API keys, tokens, or credentials
- Hardcode secrets in source files, config files, or scripts
- Deliberately expose real secret values (e.g.,
echo $SECRET, or pipingprintenv/envoutput somewhere it is logged, committed, or shown) - Include secrets in commit messages, comments, or documentation
Note on
env/printenvin the sandbox: Inside the sandbox, secrets are injected placeholders or proxied (the agent never holds the real USAi key material) — on SBX via the proxy/placeholder mechanism, on MSB via--secret ENV@HOSTswap-on-the-wire — so inspecting the environment is not automatically a leak. Theusai-providerkit's OpenCode policy is default-allow (the sandbox is the security boundary), so these commands are allowed rather than gated — the agent should still avoid deliberately dumping secret values. The prohibition above is about exposing real secret values, not about routine environment inspection in the sandbox. The gated (ask) class is instead commands that open a new outbound destination (e.g.git push, new git remotes,scp/sftp/rsync/nc); see ADR-0005 and the kit's decision record.Note on
git push: Pushing to an authorized GitHub remote works inside the sandbox — the per-sandboxGITHUB_TOKENis bound to the GitHub hosts andghuses it. If HTTPS push prompts for credentials, rungh auth setup-gitonce to install theghcredential helper, thengit push. Being gated ongit pushmeans the agent needs user approval for the push (it opens an outbound write to the remote), not that the agent is technically unable to authenticate.
All secrets MUST be accessed via:
- The backend's secret management (SBX secret store / proxy, or MSB
--secret ENV@HOSTbinding), driven throughacq - Environment variables injected at runtime (not persisted)
2. Assume You Are Untrusted
Agents must behave as if:
- The runtime environment is monitored
- Outputs may be logged and reviewed
- Any exposed secret is considered compromised
3. The Sandbox Is the Security Boundary
All agent execution MUST:
- Occur inside the sandbox (SBX or MSB) when working with USAi endpoints
- Go through
acq(or the backend CLI it wraps) — never the deprecateddocker sandboxcommands - Avoid direct host interaction unless explicitly required
- Avoid writing outside the working directory
- Respect container/VM filesystem boundaries
4. Config-First Approach
Agents should:
- Prefer modifying configuration files over writing custom scripts
- Use
opencode.jsonc(or equivalent) for model/provider setup - Avoid introducing unnecessary abstraction layers
- Document configuration changes clearly
5. Keep It Minimal
The agent MUST NOT:
- Add frameworks without justification
- Add dependencies without explicit approval
- Introduce persistence layers
- Over-engineer solutions
This repo is for:
- Testing patterns
- Documenting outcomes
- Producing reproducible examples
Permitted Actions
The agent MAY perform these actions without additional approval:
- Read files within the project directory
- Generate and modify source code and configuration
- Run linters and formatters
- Read documentation and public API references
- Create and update documentation
- Execute commands inside the sandbox (SBX or MSB)
Actions Requiring Approval
The agent MUST ask the user before:
- Installing or upgrading dependencies
- Making network requests to external services (except USAi endpoints)
- Modifying CI/CD pipeline configurations
- Deleting files or directories
- Committing or pushing code — pushing to an authorized GitHub remote is technically supported in the sandbox (via the per-sandbox
GITHUB_TOKENandgh; rungh auth setup-gitonce if HTTPS push prompts); this gate is about obtaining user approval for the outbound write, not a claim that the agent cannot authenticate - Modifying backend configuration (SBX or MSB), or creating sandboxes outside the sanctioned bootstrap (
acq run/acq create/sbx run/msb run, which auto-create a sandbox as part of normal execution and are pre-approved) - Accessing endpoints outside the approved list
Prohibited Actions
The agent MUST NEVER:
- Access files outside the project directory
- Access or modify production systems or data
- Hardcode secrets, API keys, tokens, or passwords
- Disable security controls, pre-commit hooks, or CI checks
- Bypass code review or change management processes
- Execute code downloaded from external sources without review
- Print environment variables containing secrets
- Store secrets in
.envfiles committed to the repo - Bypass the sandbox (SBX or MSB) for convenience
- Create network listeners or reverse connections
Data Handling
- Sensitive data types in this project: API keys, tokens, credentials (never stored)
- Approved data storage: Local filesystem within project directory only
- PII handling: No PII should exist in this repository
- Data residency: Local development only
The agent MUST:
- Never include API keys or tokens in logs, comments, or test fixtures
- Use environment variables injected via the sandbox backend (SBX or MSB) for all credentials
- Mask any sensitive values if debugging output is required
Network Access
- Authorized external endpoints:
https://api.gsa.usai.gov/api/v1(USAi API)https://api.github.com(GitHub API — via the SBX proxy, or the MSB--secretbinding)https://github.comandhttps://codeload.github.com(GitHub HTTPS git/tarball transport — via the SBX proxy, or the MSB--secretbinding)https://workshop.cloud.gov(GitLab API - GSA workshop instance)
- Authorized internal endpoints: None
- TLS requirement: TLS 1.2+ for all connections
- Proxy configuration: Use system proxy if configured
Credential Injection Methods
Prefer driving these through acq, which applies the right mechanism for the
selected backend. The backends differ: SBX injects via its secret store /
proxy (placeholders swapped in-sandbox); MSB binds ENV@HOST and swaps the
real value in on the wire. Both keep the real secret out of the agent's hands.
| Service | SBX | MSB | Notes |
|---|---|---|---|
| USAi | Custom secret (sbx secret set-custom -g --host api.gsa.usai.gov --env USAI_API_KEY) | acq secret set usai … → bound as USAI_API_KEY@api.gsa.usai.gov | Custom endpoint not a built-in proxy service on SBX |
| GitHub | SBX proxy, per-sandbox scoped (acq fine-grained flow, or sbx secret set <sandbox> github) | acq secret set github … → bound as GITHUB_TOKEN@github.com,api.github.com,codeload.github.com | Least-privilege per-sandbox default. Agent never sees the token. See ADR-0013 |
| GitLab | Custom secret (sbx secret set-custom -g --host workshop.cloud.gov --env GITLAB_TOKEN) | acq secret set gitlab --host workshop.cloud.gov --env GITLAB_TOKEN → bound generically as GITLAB_TOKEN@workshop.cloud.gov (custom endpoint; requires --host/--env, not a built-in bind) | Not a built-in service on either backend |
See docs/BACKEND_GUIDE.md for the full per-backend
credential-injection and secret-binding model (and
docs/howto/sbx.md for SBX-specific proxy
patterns).
Coding Standards
- Follow
CODING_PRACTICES.mdin the GSA agentic-coding-playbook for secure coding guidelines - Prefer explicit configuration over implicit behavior
- Maximum function length: 50 lines
- All external input MUST be validated before use
- Use parameterized queries for any database operations
Durable References: Cross-Link Code, Docs, and ADRs — Not Trackers
This repository must remain self-contained and outlive the issue tracker. GitHub issue/PR numbers, and internal epic labels ("gap A", "gap K", etc.), are ephemeral SaaS-dependent tracking artifacts — useful during development, but an obstacle to review and long-term maintenance once merged. The durable homes for rationale are ADRs and docs; the durable homes for behavior are the code and its tests.
The agent MUST:
- Keep code comments self-contained. Explain why in prose. A comment MAY
point to an ADR (e.g. "see ADR-0015") — that is the correct durable anchor
for a design decision. A comment MUST NOT rely on a bare
#NNN/quickstart#NNN/patterns#NNNissue-or-PR reference, or an epic "gap X" label, to carry meaning: rewrite it as prose (and cite an ADR if one applies). - Point docs → code and ADRs (what/where it is, why it was decided), and point code → docs and ADRs (the durable rationale). Prefer docs pointing at code over the reverse, except to cite an ADR.
- Before opening a PR, strip ephemeral tracker references from any code comment or doc it added or touched. Durable, cross-repo-relevant facts (a pinned release SHA, an upstream bug's observable behavior) belong in prose/ADRs, not as a bare tracker number.
The agent MAY leave issue/PR references in ephemeral, non-durable contexts:
commit messages, PR descriptions, CHANGELOG.md (release automation), and an
ADR's own Links / tracking section (where issue references are acceptable,
though prose or ADR cross-links are preferred). Test names that already encode
a regression's id MAY keep it as a stable identifier.
Fully Qualify Issue/PR References in Anything Durable
Shorthand like #233 is fine when talking to a human in this session — but
it MUST NOT land, unqualified, in anything durable or auto-linked (commit
messages, PR titles/descriptions, review comments, tracking issues, ADRs). Once
auto-linked, a bare #233 resolves relative to whatever repository renders
it — so a #233 written for GSA-TTS/agentic-coding-quickstart can silently
point at GSA-TTS/agentic-coding-patterns#233 (a different thing) when quoted or
cross-posted.
Therefore, in any durable or cross-posted artifact, the agent MUST write issue/PR references fully qualified:
- Cross-repo, always safe:
GSA-TTS/agentic-coding-quickstart#233(or a full URL). Use this form in every commit message, PR body, review comment, and tracking issue — including when referring to the current repo — because these are read and auto-linked outside their origin. - A bare
#233is acceptable only within the same repository's PR/issue body where the target is unambiguous by construction, and even then the qualified form is preferred. When in doubt, fully qualify.
This does not change the durable-reference rule above (code comments and docs prose still avoid tracker numbers entirely, qualified or not); it governs the ephemeral contexts where a reference is allowed at all.
Rationale: this is enforcement of the existing "docs-as-code" / self-contained repository discipline. Doing this continuously means no later "de-reference" or "re-qualify" cleanup pass is ever needed.
Dependencies
- Approved registries: npmjs.com, pypi.org (for tooling only)
- License restrictions: No AGPL; GPL requires justification
- Version pinning: Exact versions only, no floating ranges
- Vulnerability policy: No critical/high CVEs
Before adding any dependency, the agent MUST:
- Verify the package name is correct (check for typosquatting)
- Check for known vulnerabilities
- Verify the license is compatible
- Get user approval
Testing Requirements
- All patterns must be reproducible from scratch
- Document what worked, what failed, and why
- Verification must not expose secrets
- Test inside the sandbox (SBX or MSB), not directly on host
Periodic Re-Verification
Documented backend patterns silently rot as sbx/msb, USAi, or OpenCode
versions move. A pattern marked "works" is only trustworthy if it still runs.
The agent SHOULD:
- Re-verify documented backend patterns by running the real flow (live, not mocked) on the quarterly review cadence (or on demand when a pattern is in doubt)
- Capture the actual output and compare it against the documented claim
- When a pattern marked "works" no longer reproduces, record it in
docs/KNOWN_FAILURE_MODES.mdand open a tracking issue (per Failure Handling below)
Incident Response
If the agent discovers a potential security vulnerability:
- Stop the current task immediately
- Report the finding to the user
- Do NOT create a public issue for security vulnerabilities
- Document the finding in
docs/KNOWN_FAILURE_MODES.mdif appropriate
Agent Meta-Constraints
The agent MUST:
- Output an execution plan and wait for approval before modifying artifacts
- Fail closed on ambiguity — halt and escalate, never guess
- Not retry failed operations silently — report, diagnose, propose
- Capture errors and document failures clearly
- Propose minimal fixes for failures
Risk modes for this project:
| Mode | Scope | Requires Approval |
|---|---|---|
| Read-only | Analyze, review, answer questions | No |
| Scoped edit | Modify files identified in plan | Plan approval |
| Broad refactor | Cross-module changes | Plan + per-module approval |
| Infrastructure | Backend config (SBX or MSB), deployment, access control | Explicit per-change approval |
Engineering Discipline
The agent MUST:
- Create an ADR before: adding dependencies, changing architecture, introducing new patterns
- Not implement speculative features (YAGNI)
- Prefer 1 config file + 1 command over complex setups
- Document outcomes clearly enough for another engineer to follow
One-command bootstrap: ./acq run opencode . (creates the sandbox, mounts your project, then attaches)
One-command verify: acq exec <sandbox-name> <verify-command> (routes to sbx exec / msb exec for the active backend)
Note:
acq runis the preferred method — it creates the sandbox if needed, mounts your project, and applies the pinned kits, then attaches.
ADR location: docs/adr/
Running shellcheck locally: The repo-root
.shellcheckrcsetsextended-analysis=false, which disables ShellCheck's dataflow pass. That pass is what used to OOM-kill the process (~1.9 GB RSS) on large scripts (notablyacq.backends/msb.sh) and forced the old one-file-per-invocation workaround. With it off, memory is a non-issue (~135 MB), so you can lint in small batches. Wall-clock still grows superlinearly with the number of files in a single invocation, so batch withxargs -n8(matching the hook):printf '%s\n' acq acq.backends/*.sh \ scripts/test-acq-lib.sh scripts/test-acq-bats test/bats/*.bats test/bats/helper.bash \ | xargs -r -n8 shellcheck --severity=warning
.shellcheckrcis picked up automatically (ShellCheck walks up to the repo root), so no extra flags are needed;--severity=warningmatches the hook. Core correctness checks (SC2086/2154/2034/1090/…) are unaffected by the dataflow pass being off. Do not pass-x/--external-sourceson the test suite: it pulls the shared stub library into every.batsfile and re-triggers the memory blow-up.
Approved Patterns
Model Configuration
- Use OpenAI-compatible providers
- Use environment variable injection for API keys
- Use explicit
baseURLfor USAi endpoints
Execution
acq run opencode .is the sanctioned bootstrap — it auto-creates a sandbox (mounting this clone as global config) and is pre-approved- Prefer
acqfor running agents and managing sandboxes; it auto-creates the sandbox on the selected backend (SBX or MSB) - Backend CLIs (
sbx run,sbx create/sbx exec;msb run,msb exec) are available for manual management, butacqis preferred - Avoid long-lived sandboxes unless required for testing
- Do NOT use deprecated
docker sandboxcommands
Disallowed Patterns
- Storing API keys in
.envfiles committed to repo - Printing environment variables to stdout
- Bypassing the sandbox (SBX or MSB) for convenience
- Embedding credentials in config files
- Over-engineering simple tests
- Using deprecated
docker sandboxcommands (use thesbxCLI, oracq, instead) - Assuming Docker Desktop is required (it is not — both SBX and MSB are standalone)
Expected Outputs
Agents should produce:
- Clean, minimal config files
- Reproducible command examples
- Documentation of:
- What worked
- What failed
- Why
Failure Handling
If something fails:
- Do NOT guess silently
- Capture the error
- Document the failure clearly
- Propose a minimal fix
- Update
docs/KNOWN_FAILURE_MODES.mdif it's a new pattern
Track Deferred Work — Deferring Is Fine, Untracked Is Not
Every identified follow-up — including work being deferred or blocked on something else ("revisit once X lands") — MUST be captured durably: a GitHub issue, or an entry in docs/KNOWN_FAILURE_MODES.md. Deferring is acceptable; leaving the work untracked is not. A code TODO or a conversation note is not tracking — it gets forgotten. Record the trigger that should unblock the work when it is deferred for a dependency.
Success Criteria
A task is complete when:
- It is reproducible from scratch
- It does not expose secrets
- It works inside the sandbox (SBX or MSB) without host dependencies
- It is documented clearly enough for another engineer to follow
Contacts
- Project Lead: William Zujkowski
- Security Contact: Project Lead
- ISSO: N/A (sandbox environment)
Agent Setup
This file follows the AGENTS.md standard and is read natively by 25+ tools including Codex, Copilot, Cursor, Windsurf, Amp, and Devin.
Most tools need no additional configuration. If your tool doesn't auto-detect AGENTS.md, add one of these:
| Tool | Config file | Content |
|---|---|---|
| Aider | .aider.conf.yml | read:\n - AGENTS.md |
| Gemini CLI | .gemini/settings.json | {"agentInstructions": "Read AGENTS.md"} |
Only create these files if you use that specific tool. Delete any you don't need.