Git Workflows for Prompt, Tool, and Config Changes
Prompt packs, tool schemas, and runtime pins change agent behavior as much as Python modules do.
Use a deliberate branch, review, and path-filter workflow so config ships with the same care as code - and so prompt-only fixes do not get buried under unrelated refactors.
Summary
Keep agent behavior files in a known tree, open focused branches per concern (prompt vs tools vs host code), require review via CODEOWNERS, run pack-aware CI path filters, and ship through a pin so production never means "whatever is on disk on the box."
Recipe
- Define a stable tree:
agent_pack/prompts,agent_pack/tools,agent_pack/policies,deploy/pins. - Pick a branch naming scheme:
prompt/...,tools/...,config/...,agent/...for mixed. - Prefer immutable version files (
system_v3.txt) over silent overwrites of a single live file. - Keep PRs single-purpose: one behavior story per PR when possible.
- Route
agent_pack/**anddeploy/pins/**through CODEOWNERS (agent + safety reviewers). - Wire CI path filters so pack edits always run evals / schema checks.
- Merge only after human review of the diff text, not just "tests green."
- Promote via pin update (and canary when risk is high), not by SSH-editing prod files.
- Tag or record release pins so rollback is a known previous file, not a guess.
- Document the workflow in onboarding so hires do not invent private processes.
Working Example
"""Minimal helpers a team might share for pack-oriented PR hygiene."""
from __future__ import annotations
import json
import re
from pathlib import Path
PACK = Path("agent_pack")
BRANCH_RE = re.compile(r"^(prompt|tools|config|agent|eval)/[a-z0-9._-]+$")
def assert_branch_name(name: str) -> None:
if not BRANCH_RE.match(name):
raise ValueError(
f"unexpected branch {name!r}; use prompt|tools|config|agent|eval prefix"
)
def list_changed_pack_files(paths: list[str]) -> list[str]:
return sorted(
p
for p in paths
if p.startswith("agent_pack/") or p.startswith("deploy/pins/")
)
def validate_tools_json(path: Path) -> None:
data = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(data, list):
raise ValueError(f"{path} must be a JSON array of tool definitions")
for i, tool in enumerate(data):
if "name" not in tool or "parameters" not in tool:
raise ValueError(f"{path} tool[{i}] missing name or parameters")
def pr_checklist(changed: list[str]) -> list[str]:
items = [
"Diff reviewed as behavior change (not only code style)",
"No secrets or raw prod transcripts in pack files",
"Pin / version fields updated if this ships alone",
]
if any(p.endswith(".json") and "/tools/" in p for p in changed):
items.append("Tool schema: dual-support plan if breaking")
items.append("Eval cases covering new or renamed tools")
if any("/prompts/" in p for p in changed):
items.append("Gold-set eval run or explicit waiver with owner")
return items
# Demo: simulate a prompt-only PR file list
changed = [
"agent_pack/prompts/system_v2.txt",
"deploy/pins/active.json",
]
print("pack files:", list_changed_pack_files(changed))
for line in pr_checklist(changed):
print("-", line)Example branch and commit flow (shell):
git checkout main && git pull --ff-only
git checkout -b prompt/refund-policy-v2
# add agent_pack/prompts/system_v2.txt (immutable new version)
# point deploy/pins/staging.json at prompt_version=v2
git add agent_pack deploy/pins/staging.json
git commit -m "prompt: add system_v2 refund policy wording"
# open PR → CODEOWNERS review → eval CI → merge → promote pinDeep Dive
Why separate branch prefixes help
| Prefix | Typical files | Review focus |
|---|---|---|
prompt/ | agent_pack/prompts/** | Policy tone, refusal, tool guidance |
tools/ | agent_pack/tools/**, tool host code | Schema compatibility, side effects |
config/ | flags, model routes, spend caps | Cost, latency, blast radius |
eval/ | gold sets, scorers | Suite integrity, no silent retarget |
agent/ | mixed host + pack | Full release train discipline |
Humans scanning the PR list immediately know risk class. CI can also key notifications off prefixes.
Path filters without false security
Example idea for GitHub Actions-style CI:
on:
pull_request:
paths:
- "agent_pack/**"
- "deploy/pins/**"
- "evals/**"
- "src/agent/**"Also run a nightly full suite on main so path filters cannot hide cross-file breakage forever.
CODEOWNERS sketch
# .github/CODEOWNERS
/agent_pack/ @team-agent-owners @team-safety
/deploy/pins/ @team-agent-owners @team-platform
/evals/ @team-agent-ownersTreat tool schema breaks like API breaks. A drive-by rename of a required property is a compatibility project.
Mixed code + pack changes
When host code must understand a new tool field:
- Land backward-compatible host support first (or same PR with careful order).
- Add schema + prompt + evals.
- Pin workers and pack together, or gate the new tool name behind a flag until workers roll.
Never pin a pack that only new code can load onto old workers. See Versioning Prompts and Tool Schemas Alongside Code.
Prompt-only hotfixes
Allow a fast path that is still reviewable:
- Branch from main.
- Add
system_vN+1(or minimal patch file if your loader supports overlays). - Required reviewer + eval smoke.
- Promote pin with short canary when tools can spend money or send external messages.
"SSH and edit prod prompt" is not a workflow; it is an incident in slow motion.
Config and secrets
Workflow rules:
- Secrets stay in a vault or CI secret store, never in pack commits.
.env.examplelists names only.- Model IDs belong in pins; API keys do not.
Review rituals that catch agent-specific bugs
Reviewers should ask:
- Does this change tool eligibility or autonomy?
- Could conflict markers or truncated diff hide a deleted policy line?
- Are few-shots still redacted and licensed?
- Does the pin in the PR match what we intend to canary?
Gotchas
- One mega-PR mixing refactors, dependency bumps, and prompt rewrites - impossible to review as behavior.
- Editing the only
system.txtin place so history cannot reconstruct what shipped yesterday. - Path filters that omit
agent_pack/**so pack PRs merge with zero evals. - Approving on green CI without reading the prompt diff - models will follow the new text, bugs included.
- Force-pushing rewritten pack history after ship without recording content hashes on pins.
- Letting generated assistant commits skip CODEOWNERS because they "look fine."
- Updating prod pin in the same commit as unfinished dual-support code.
Alternatives
| Approach | Strength | Weakness |
|---|---|---|
| Git packs + PR + pin (this recipe) | Reviewable, CI-friendly, rollbackable | Needs loader discipline |
| Prompt hub as sole source of truth | Fast UI edits | Weak PR culture unless mirrored to git |
| Feature-flag payloads only | Instant toggles | Easy to skip review if flags edited live |
| Monorepo trunk with no pack ownership | Simple ACLs | High conflict and drive-by policy edits |
| Separate config repo | Clear isolation | Version skew vs host code |
Mature teams often author in git and serve the active pin via a config service or flags.
FAQs
Should prompt changes always require the same reviewers as security-sensitive code?
When tools can move money, delete data, or message customers, yes. Route those paths to safety/agent owners via CODEOWNERS.
Rebase or merge for pack branches?
Follow the team default. What matters more is frequent integration with main so conflicts stay small and readable.
Can non-engineers open prompt PRs?
Yes if the workflow is documented, the editor is clear, and an agent owner still reviews impact and evals.
How small should a prompt PR be?
One coherent behavior change. Split "tone pass" from "new tool instructions" when both are large.
Do we need release branches?
Not always. Many teams ship from main with pins and flags. Use release branches when compliance or multi-service trains require them.
How do we mark a breaking tool schema in git?
New version file, changelog note, dual registration period, and eval cases for old and new. Do not reuse the same version label.
Where do model route changes go?
In the pin or a versioned config file under the same review rules as prompts. Model swaps change quality, cost, and tool calling.
What about emergency reverts?
Prefer pin rollback to a previous immutable pack. git revert on main is fine for the source of truth; production still needs the pin flip. See Rollback Strategies When a Deployed Agent Regresses.
Should eval fixtures live in the same PR as the prompt?
When the product behavior intentionally changes, update fixtures in the same PR. Do not silently weaken assertions to pass a bad prompt.
How do monorepo path filters interact with shared libraries?
If shared tool code lives outside src/agent, include those paths in the eval workflow triggers or you will miss breakages.
Related
- Why Agent Teams Still Need Solid Git and Linux Fundamentals - why workflow rigor exists
- Git & Linux Basics for Agent Developers - first branch and commit skills
- Common Git Conflicts in Prompt and Config Files - when branches collide
- Documenting Agent-Specific Conventions for New Team Members - write the workflow down
- Git, Linux CLI & Team Onboarding Best Practices - section habits
- Versioning Prompts and Tool Schemas Alongside Code - pack layout and pins
- Running Eval Suites as a CI Gate Before Deploy - block bad scores
- What "Continuous Deployment" Means for a Prompt-Driven System - behavior deploys
Stack versions: Pins from the category manifest (verify at build): OpenRouter (~315+ models, July 2026 pricing/fees); LangGraph 1.0+; CrewAI 1.14+; Microsoft Agent Framework 1.0; Vercel AI SDK 6; Pydantic AI (latest); LlamaIndex (latest); OpenAI Agents SDK (latest + MCP); MCP (Linux Foundation governance); A2A (HTTP+SSE+JSON-RPC 2.0); Solana
@solana/web3.js+@solana/spl-token.