-
Notifications
You must be signed in to change notification settings - Fork 16
docs: add configuration checklist for agent feature work #566
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
5429e08
docs: add configuration checklist for agent feature work
ralphbean de9d4bc
docs: fix technical inaccuracies in FEATURES.md
fullsend-ai-coder[bot] b677240
docs: add LOCAL.md for local testing and link from FEATURES/CONTRIBUTING
ralphbean 34e75ab
docs: address review feedback on FEATURES.md
ralphbean 245280b
docs: address review feedback on feature checklist and local guide
ralphbean f96ddf3
docs: drop runner_env references, clarify harness defaults
ralphbean 5a4b3f1
docs: clarify config.yaml vs env var surface in FEATURES.md
ralphbean ea26bd2
docs(#566): fix ADR misattribution and local testing example bugs
ralphbean 06e4e05
fix(#566): address review feedback on config checklist docs
ralphbean 10f9728
docs: fix skill-override composition and generated-script guidance
ralphbean 579fb94
docs(#566): address remaining review feedback
ralphbean f849973
docs(#566): address remaining review feedback
ralphbean File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| # Adding a Configuration Option to an Agent | ||
|
|
||
| Checklist for introducing a new configurable behavior to an agent. | ||
| Use this to avoid missing integration points — the system has several | ||
| layers and a change that only touches one may silently fail or not behave as | ||
| you expect. | ||
|
|
||
| A new configuration option often falls into one of three categories: | ||
|
|
||
| 1. **Scripts only** — the change lives entirely in the pre-script or | ||
| post-script. The agent prompt and skills are unchanged. Example: | ||
| gating whether the agent runs at all based on an env var. | ||
| 2. **Agent only** — the change lives in the agent prompt or a skill. | ||
| The pre/post scripts are unchanged. Example: adding a skill that | ||
| changes how the agent evaluates an issue. | ||
| 3. **Agent + scripts** — the agent needs to produce new information and | ||
| the post-script needs to consume it. This usually also requires a | ||
| schema update (`schemas/<agent>-result.schema.json`) to accommodate | ||
| whatever new field the agent uses to expose its conclusions to the | ||
| post-script. Example: the `requires_workflow_changes` flag in triage. | ||
|
|
||
| ## 1. Decide what changes and what stays the same | ||
|
|
||
| Before writing code, answer: | ||
|
|
||
| - **What is the current default behavior?** Document it explicitly. | ||
| - **Will the default change?** If yes, that could be considered a breaking | ||
| change. Prefer keeping the existing behavior as the default and making the | ||
| *new* behavior opt-in. | ||
|
|
||
| ## 2. Choose the configuration surface | ||
|
|
||
| | Surface | When to use | Example | | ||
| |---------|-------------|---------| | ||
| | **Environment variable** | Runtime behavior toggle, simple values, specific to one agent — per ADR 0080 (fullsend-ai/fullsend), this is single-agent behavior tuning rather than a `config.yaml` field. Repo owners set it in their base-derived harness files, overriding via `base:` composition (ADR 0045). Per ADR 0049, it must use an `{AGENT}_` prefix. Per ADR 0081, the CI workflow `env:` block is reserved for infrastructure plumbing (credentials, project IDs, regions) — don't use workflow inputs to set a behavior knob's value, except for values only computable at CI runtime. We recommend picking one surface per option — either an env var or a `config.yaml` option, not both — to avoid two sources of truth. | `TRIAGE_AUTO_CODE` | | ||
| | **`config.yaml` option** | The option should be respected by *every* agent, not just one — no agent-specific prefix, and not configurable via env var. | the cross-repo allow list | | ||
| | **Skill override** | The behavior is best expressed as natural-language instructions to the agent. Repo owners drop a replacement skill in `.agents/skills/`. Org owners override via `base:` composition (ADR 0045) — inherit the upstream harness and add the skill under `skills:` with the same basename as the one being replaced, so the merge dedupes by basename (fullsend-ai/fullsend #5409) and it wins. The older `customized/skills/` overlay in the org `.fullsend` config repo is deprecated by ADR 0064. | `issue-labels` skill | | ||
|
|
||
| Environment variables are the simplest for end users to configure. | ||
| Skills are more flexible — they let repo or org owners override | ||
| behavior with natural-language instructions without forking the agent | ||
| definition. A `config.yaml` option requires a schema update in | ||
| fullsend-ai/fullsend plus a follow-up campaign to make each agent | ||
| respect it; an env var option can be delivered entirely within this | ||
| repo. | ||
|
|
||
| ## 3. Env var placement — sandbox vs. runner vs. both | ||
|
|
||
| The harness separates the sandbox (where the agent runs) from the | ||
| runner (where pre/post scripts run). An env var must be in the right | ||
| place: | ||
|
|
||
| | Where the var is read | Where to declare it | | ||
| |-----------------------|---------------------| | ||
| | Agent prompt only (sandbox) | `env: sandbox:` in `harness/<agent>.yaml` | | ||
|
ralphbean marked this conversation as resolved.
ralphbean marked this conversation as resolved.
|
||
| | Pre/post script only (runner) | `env: runner:` in `harness/<agent>.yaml` | | ||
| | Both agent and scripts | Both sandbox and runner sections | | ||
|
ralphbean marked this conversation as resolved.
|
||
|
|
||
| Use `forge.github.env.sandbox` / `forge.github.env.runner` only when | ||
|
ralphbean marked this conversation as resolved.
|
||
| you need environment variables with different values between GitHub and | ||
| GitLab. | ||
|
|
||
| ## 4. Update the subagent definition file | ||
|
|
||
| If the agent needs to know about the new option: | ||
|
|
||
| - [ ] Reference the env var in `agents/<agent>.md` wherever it fits | ||
|
ralphbean marked this conversation as resolved.
|
||
| naturally in the prompt flow (per ADR 0049, there is no required | ||
| section structure for how agent prompts reference config vars). | ||
| If the file has an `## Inputs` section, that's a reasonable place; | ||
| otherwise, weave it into the existing prompt context. | ||
| - [ ] Add conditional behavior to the agent prompt. Keep it minimal — | ||
| describe the env var's meaning and what the agent should do | ||
| differently. Don't add a paragraph where a sentence will do. | ||
|
ralphbean marked this conversation as resolved.
|
||
| - [ ] If the default is "do what you already do," make the prompt change | ||
| a conditional block: "If `$VAR` is set to `X`, then..." | ||
|
ralphbean marked this conversation as resolved.
|
||
| - [ ] Exhort the agent to expose new information via its output schema, if | ||
| necessary for processing in the post script. | ||
|
|
||
| ## 5. Update pre/post scripts | ||
|
ralphbean marked this conversation as resolved.
|
||
|
|
||
| Ask yourself: | ||
|
|
||
| - [ ] **Pre-script:** Does the new option affect how the agent gathers input | ||
| before it runs? Does the new option affect whether the agent should run at | ||
| all? The [`skipped=true` | ||
| mechanism](https://fullsend.sh/docs/normative/prescript-output/v1/) | ||
| in the pre-script lets you skip the agent entirely based on configuration. | ||
| - [ ] **Post-script:** Does the new option change how the agent's output | ||
| is applied? If your option changes output label behavior, comment | ||
|
ralphbean marked this conversation as resolved.
|
||
| content, or whether to suppress output entirely, the post script is where | ||
| that logic lives. | ||
| - [ ] **Both:** Some features may require changes in both. | ||
| - [ ] **Generated scripts:** `scripts/pre-code.sh`, `scripts/post-code.sh`, | ||
| `scripts/post-fix.sh`, and `scripts/post-prioritize.sh` are generated | ||
| from the corresponding `scripts/<name>.src.sh` — edit the `.src.sh` | ||
| file and run | ||
| `make script-build` to regenerate the committed `.sh`. Run | ||
| `make check-bundle` (required in CI) to verify before opening the PR. | ||
|
|
||
| ## 6. Update the harness definition | ||
|
ralphbean marked this conversation as resolved.
ralphbean marked this conversation as resolved.
|
||
|
|
||
| In `harness/<agent>.yaml`: | ||
|
|
||
| - [ ] Add the env var to the appropriate sections (see step 3) | ||
| - [ ] Set the default value directly in the harness YAML (e.g., | ||
| `MY_VAR: "default_value"`). Users override defaults in their | ||
| base-derived harness files — the base harness is where sensible | ||
| defaults belong. | ||
| - [ ] The harness engine uses Go's `os.Expand` for variable substitution, | ||
| which supports `$VAR` and `${VAR}` only — **not** shell default | ||
| syntax like `${VAR:-default}`. Don't use `${VAR:-default}` in | ||
| harness YAML values; it won't work. | ||
|
|
||
| ## 7. Update the schema (if the agent output changes) | ||
|
|
||
| If the new option adds a field to the agent's JSON output: | ||
|
|
||
|
ralphbean marked this conversation as resolved.
ralphbean marked this conversation as resolved.
|
||
| - [ ] Add the field to `schemas/<agent>-result.schema.json` | ||
| - [ ] Make it optional (`"required"` array unchanged) unless every | ||
| invocation must produce it | ||
| - [ ] Add conditional validation in `allOf` if the field is required | ||
| only for certain actions | ||
| - [ ] Run `scripts/validate-output-schema-test.sh` to verify | ||
|
|
||
| ## 8. Check skill impact | ||
|
|
||
| If your change modifies a skill rather than (or in addition to) the | ||
| agent prompt: | ||
|
|
||
| - [ ] Check which other agents use that skill: | ||
| `grep -r '<skill-name>' agents/ harness/` | ||
| - [ ] If the env var is agent-specific, consider whether or not it should be | ||
| baked into that skill. Keep agent-specific logic in the agent prompt; | ||
| keep reusable judgment in the skill. | ||
| - [ ] If you add a new skill, add it to `harness/<agent>.yaml` under | ||
| `skills:` and to the agent frontmatter `skills:` array. | ||
|
|
||
| ## 9. Update documentation | ||
|
|
||
| - [ ] `docs/<agent>.md` — add the variable to the `### Variables` | ||
| table. If the table says "None," replace it. | ||
| - [ ] Keep the description to one line in the table; link to and expand a | ||
| section below if it needs explanation. | ||
| - [ ] If you added or modified a skill, update its `SKILL.md` and | ||
| document it in `docs/<agent>.md` under the `### Skill:` section | ||
| (see `docs/triage.md` for an example with `issue-labels`). | ||
|
|
||
| ## 10. Update tests | ||
|
|
||
| - [ ] **Post-script tests** (`scripts/post-<agent>-test.sh`) — add | ||
| cases for the new option: default behavior preserved, option | ||
| set to each valid value, invalid/empty values handled. | ||
| - [ ] **Pre-script tests** (if the pre-script changed). | ||
| - [ ] **Schema tests** (`scripts/validate-output-schema-test.sh`) — if | ||
| you changed the schema. | ||
| - [ ] Run the full test suite: `make test` | ||
|
|
||
| ## 11. Check network policy | ||
|
|
||
| If the new option requires the agent to reach a new external service | ||
| from the sandbox: | ||
|
|
||
| - [ ] Update `policies/<agent>.yaml` to allow the new host/port | ||
| - [ ] This is rare — most configuration changes don't need network | ||
| changes | ||
|
|
||
| ## 12. Review checklist | ||
|
|
||
| Before opening the PR, verify: | ||
|
|
||
| - [ ] The existing default behavior is preserved when the option is | ||
| unset, unless you're sure it should change | ||
| - [ ] The env var appears in every layer it needs to (env file, harness | ||
| yaml sandbox/runner, forge sections) | ||
| - [ ] Tests cover both the default and the configured case | ||
|
ralphbean marked this conversation as resolved.
|
||
| - [ ] Documentation is updated | ||
| - [ ] No other agent is broken by a skill change | ||
| - [ ] The tests pass: `make test` | ||
| - [ ] Manually tested with `fullsend run` (see [LOCAL.md](LOCAL.md)) | ||
|
|
||
| ## 13. Consider a functional eval test (optional) | ||
|
|
||
| If the feature changes agent judgment or output in a way that unit | ||
| tests can't cover, consider adding a functional eval case under | ||
| `eval/<agent>/cases/`. These are expensive — they consume model tokens | ||
| and create ephemeral GitHub repos — so only add one when the change | ||
| meaningfully affects end-to-end behavior. See [eval/README.md](eval/README.md) | ||
| for the test case structure. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| # Testing Agent Changes Locally | ||
|
|
||
| This guide covers how to test agent changes in this repo on your local | ||
| machine. For general background on running agents locally, see | ||
| [Running agents locally](https://fullsend.sh/docs/guides/user/running-agents-locally.html). | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - **fullsend** CLI on your `PATH` | ||
| - **gh** CLI authenticated (`gh auth status`) | ||
| - **openshell** and **openshell-gateway** installed, matching the version | ||
| fullsend pins in | ||
| [`openshell-version.sh`](https://github.com/fullsend-ai/fullsend/blob/main/.github/scripts/openshell-version.sh) | ||
| (currently 0.0.83) — an older version (e.g. the Homebrew tap's 0.0.73) | ||
| can fail the sandbox pre-flight with an opaque `GitHub API unreachable | ||
| from sandbox` error | ||
| - **podman** installed | ||
| - A test repo with issues you can point agents at (e.g., | ||
| `your-org/test-repo`) | ||
|
|
||
| For installation of openshell and fullsend, see | ||
| [Running agents locally](https://fullsend.sh/docs/guides/user/running-agents-locally.html). | ||
|
|
||
| ## Starting the sandbox infrastructure | ||
|
|
||
| Before running an agent, you need the podman socket (or podman machine | ||
| on macOS) and the openshell gateway running. See | ||
| [Running agents locally](https://fullsend.sh/docs/guides/user/running-agents-locally.html) | ||
| for platform-specific setup instructions covering both Linux and macOS. | ||
|
|
||
| ## Running an agent with `fullsend run` | ||
|
|
||
| The simplest way to test is to run the agent directly against a real | ||
| GitHub issue. | ||
|
|
||
| ### 1. Set environment variables | ||
|
ralphbean marked this conversation as resolved.
|
||
|
|
||
| Export the variables the agent needs: | ||
|
|
||
| ```bash | ||
| export GITHUB_ISSUE_URL="https://github.com/your-org/test-repo/issues/25" | ||
| export GH_TOKEN="$(gh auth token)" | ||
|
|
||
| # GCP/Vertex AI credentials — required by most agents via | ||
| # common/env/gcp-vertex.env and the host_files GOOGLE_APPLICATION_CREDENTIALS | ||
| # mount in harness YAML. | ||
| export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-key.json" | ||
| export ANTHROPIC_VERTEX_PROJECT_ID="your-gcp-project-id" | ||
| export GOOGLE_CLOUD_PROJECT="your-gcp-project-id" | ||
| export CLOUD_ML_REGION="global" | ||
| ``` | ||
|
|
||
| If you're testing a new env var, export it here too. You can also use | ||
| `--env-file` with a dotenv file if you prefer. | ||
|
|
||
| ### 2. Clone the target repo | ||
|
|
||
| `GITHUB_ISSUE_URL` above points at an issue in a separate repo (e.g. | ||
| `your-org/test-repo`) — clone it to its own local path so `--target-repo` | ||
| has real content to work against: | ||
|
|
||
| ```bash | ||
| git clone git@github.com:your-org/test-repo /tmp/target-repo | ||
| ``` | ||
|
|
||
| ### 3. Run the agent | ||
|
|
||
| ```bash | ||
| fullsend run triage \ | ||
| --fullsend-dir . \ | ||
| --target-repo /tmp/target-repo \ | ||
| --output-dir /tmp/fullsend | ||
| ``` | ||
|
|
||
| - `--fullsend-dir .` tells fullsend to use this repo's harness files. | ||
| - `--target-repo` points at the target repo checkout (from step 2) for | ||
| the agent to work against. Don't point it at `.` — that's this | ||
| harness repo, not the repo the issue lives in. | ||
| - `--output-dir /tmp/fullsend` pins the output location so the `cat` | ||
| command in step 4 works as written. Without it, fullsend defaults to | ||
| Go's `os.TempDir()/fullsend`, which is `/tmp/fullsend` on Linux but | ||
| `$TMPDIR/fullsend` (something like | ||
| `/var/folders/.../T/fullsend/`) on macOS. | ||
| - Add `--no-post-script` to inspect the agent's output without | ||
| applying GitHub mutations (posting comments, applying labels). For | ||
| features that change post-script behavior, you'll want to run | ||
| without this flag — just point at a test issue where you don't mind | ||
| making changes. | ||
|
|
||
| Some agents need additional variables beyond the ones above — check the | ||
| target agent's `harness/<agent>.yaml` (top-level `runner_env`, `env: | ||
| runner:`, and `forge.<forge>.runner_env`) for what it expects, and | ||
| export those before running. | ||
|
|
||
| ### 4. Inspect the output | ||
|
|
||
| The agent writes its result JSON to the output directory printed by | ||
| `fullsend run`. Check it to verify your new configuration option | ||
| produced the expected output: | ||
|
|
||
| ```bash | ||
| cat /tmp/fullsend/agent-triage-*/iteration-*/output/agent-result.json | jq . | ||
|
ralphbean marked this conversation as resolved.
|
||
| ``` | ||
|
|
||
| ## Testing a new configuration option | ||
|
|
||
| When testing a new env var, verify both cases: | ||
|
|
||
| 1. **Unset** — run without the var and confirm the default behavior is | ||
| preserved. | ||
| 2. **Set** — run with the var set to each valid value and confirm the | ||
| new behavior works. | ||
|
|
||
| Example testing a hypothetical `TRIAGE_AUTO_CODE` var: | ||
|
|
||
| ```bash | ||
| # Default behavior (var unset) | ||
| fullsend run triage \ | ||
| --fullsend-dir . \ | ||
| --target-repo /tmp/target-repo \ | ||
| --output-dir /tmp/fullsend | ||
|
|
||
| # New behavior (var set) | ||
| export TRIAGE_AUTO_CODE=off | ||
| fullsend run triage \ | ||
| --fullsend-dir . \ | ||
| --target-repo /tmp/target-repo \ | ||
| --output-dir /tmp/fullsend | ||
| ``` | ||
|
|
||
| ## Functional eval tests | ||
|
|
||
| The `eval/` directory contains functional test scenarios that run agents | ||
| against ephemeral GitHub repos and score the results. See | ||
| [eval/README.md](eval/README.md) for setup and usage. | ||
|
|
||
| To run triage evals: | ||
|
|
||
| ```bash | ||
| EVAL_ORG=my-org ./eval/run-functional.sh triage | ||
| ``` | ||
|
|
||
| Eval tests are expensive (they consume model tokens and create real | ||
| GitHub repos). Use them when you need to verify end-to-end behavior | ||
| for a significant change, not for every iteration. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.