diff --git a/README.md b/README.md index b61aeba..1c16546 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,41 @@ error_handling: channel: "#eng-reviews" ``` + +### Multi-Agent Coordination via GNAP + +When multiple gitagent-defined agents need to work together on shared tasks, use [GNAP (Git-Native Agent Protocol)](https://github.com/farol-team/gnap) as the coordination layer. A shared git repo acts as a persistent, auditable task board — no orchestrator process required. + +``` +coordination-board/ # shared GNAP repo (separate from agent repos) +├── board/ +│ ├── todo/ +│ │ └── analyze-report.md # task waiting to be claimed +│ ├── doing/ +│ │ └── write-summary.md # claimed by agent-b (owner set in front-matter) +│ └── done/ +│ └── fetch-data.md # completed with output appended +``` + +Agents coordinate by committing file moves: `todo/ → doing/ → done/`. Every transition is a git commit — full audit trail, no extra infrastructure. + +**Task file format:** + +```markdown +--- +id: analyze-report-001 +priority: high +owner: null +required_role: analyst +--- +# Analyze Q1 Report +... +``` + +**SOD integration:** combine `required_role` in task files with `conflicts` in `agent.yaml` to prevent the same agent from both creating and completing high-stakes tasks. + +See [`examples/gnap-coordination/`](examples/gnap-coordination/) for a full working example with a SkillsFlow workflow that polls the board, claims tasks, and writes results. + ### Porting Framework Agents to GitAgent Agents built in frameworks like NVIDIA AIQ, LangGraph, or CrewAI have their identity split across config files, Jinja2 templates, and Python code. gitagent extracts the **identity layer** — prompts, rules, roles, tool schemas — into a portable, versionable format. diff --git a/examples/gnap-coordination/README.md b/examples/gnap-coordination/README.md new file mode 100644 index 0000000..73eb439 --- /dev/null +++ b/examples/gnap-coordination/README.md @@ -0,0 +1,56 @@ +# GNAP Coordination Example + +This example shows how to use GNAP (Git-Native Agent Protocol) as the coordination layer for multiple gitagent-defined agents. + +## What is GNAP? + +[GNAP](https://github.com/farol-team/gnap) is a git-native coordination protocol where a shared repo acts as a persistent, auditable task board. Agents communicate by reading and writing files — no orchestrator process required. + +## Board Structure + +``` +board/ +├── todo/ # tasks waiting to be claimed +├── doing/ # tasks currently in progress (claimed by an agent) +└── done/ # completed tasks with outputs +``` + +Each task is a markdown file with a YAML front-matter header: +```markdown +--- +id: task-001 +priority: high +owner: null # set to AGENT_ID when claimed +required_role: analyst +--- + +# Task description... +``` + +## How it works with gitagent + +1. **Definition layer (gitagent):** Each agent is defined by `agent.yaml` + `SOUL.md` with clear roles via `DUTIES.md` +2. **Coordination layer (GNAP):** Agents share a git repo as a task board, coordinating via commits +3. **SOD enforcement:** `required_role` in task files + `conflicts` in `agent.yaml` prevents the same agent from creating and completing high-stakes tasks + +## Running the example + +```bash +# Set up the coordination board +git init gnap-board && cd gnap-board +mkdir -p board/{todo,doing,done} +git add . && git commit -m "init: gnap board" + +# Configure the worker agent +export GNAP_BOARD_URL="file:///path/to/gnap-board" +export AGENT_ID="worker-1" + +# Run the workflow +gitagent run . --adapter git +``` + +## Further reading + +- [GNAP specification](https://github.com/farol-team/gnap) +- [gitagent SkillsFlow docs](../../spec/SPECIFICATION.md) +- [Segregation of Duties pattern](../../README.md#segregation-of-duties-sod) diff --git a/examples/gnap-coordination/agent.yaml b/examples/gnap-coordination/agent.yaml new file mode 100644 index 0000000..85353c2 --- /dev/null +++ b/examples/gnap-coordination/agent.yaml @@ -0,0 +1,32 @@ +spec_version: "0.1.0" +name: gnap-worker +version: 0.1.0 +description: > + Example agent that coordinates with peers via a shared GNAP board. + Claims tasks from board/todo/, processes them, moves to board/done/. + +model: + preferred: claude-sonnet-4-6 + +compliance: + segregation_of_duties: + roles: + - id: analyst + description: Processes analysis tasks + permissions: [claim, process, complete] + - id: reviewer + description: Reviews completed work + permissions: [review, approve, reject] + conflicts: + - [analyst, reviewer] + assignments: + gnap-worker: [analyst] + enforcement: strict + +environment: + - name: GNAP_BOARD_URL + description: URL of the shared GNAP coordination git repo + required: true + - name: AGENT_ID + description: Unique identifier for this agent instance + required: true diff --git a/examples/gnap-coordination/board/todo/analyze-report.md b/examples/gnap-coordination/board/todo/analyze-report.md new file mode 100644 index 0000000..3b5e81a --- /dev/null +++ b/examples/gnap-coordination/board/todo/analyze-report.md @@ -0,0 +1,18 @@ +--- +id: analyze-report-001 +priority: high +owner: null +created_by: orchestrator +created_at: 2026-03-15T10:00:00Z +required_role: analyst +--- + +# Analyze Q1 Report + +Analyze the Q1 financial report and extract key metrics. + +## Input +- file: knowledge/q1-report.pdf + +## Expected Output +- metrics: revenue, growth_rate, top_risks diff --git a/examples/gnap-coordination/workflows/gnap-worker-flow.yaml b/examples/gnap-coordination/workflows/gnap-worker-flow.yaml new file mode 100644 index 0000000..af92119 --- /dev/null +++ b/examples/gnap-coordination/workflows/gnap-worker-flow.yaml @@ -0,0 +1,50 @@ +name: gnap-worker-flow +description: Claim and process tasks from a shared GNAP coordination board + +triggers: + - schedule: "*/5 * * * *" # poll board every 5 minutes + +steps: + claim: + tool: bash + inputs: + command: | + git clone $GNAP_BOARD_URL /tmp/board + cd /tmp/board + TASK=$(ls board/todo/ | head -1) + if [ -z "$TASK" ]; then echo "no_task"; exit 0; fi + git mv board/todo/$TASK board/doing/$TASK + sed -i "s/owner: null/owner: $AGENT_ID/" board/doing/$TASK + git commit -m "claim: $TASK by $AGENT_ID" + git push + echo $TASK + + process: + agent: analyst + depends_on: [claim] + conditions: + - ${{ steps.claim.outputs.stdout != 'no_task' }} + inputs: + task_file: board/doing/${{ steps.claim.outputs.stdout }} + + complete: + tool: bash + depends_on: [process] + inputs: + command: | + cd /tmp/board + TASK="${{ steps.claim.outputs.stdout }}" + git mv board/doing/$TASK board/done/$TASK + echo "\n\n## Output\n${{ steps.process.outputs }}" >> board/done/$TASK + git commit -m "done: $TASK" + git push + +error_handling: + on_failure: + tool: bash + inputs: + command: | + cd /tmp/board + git mv board/doing/$TASK board/todo/$TASK + git commit -m "requeue: $TASK (failed)" + git push