Agent Ci Workflow
Autonomous agent workflow with CI integration
An AI coding agent that orients at startup via pm context, searches before creating, claims tasks, links evidence, and auto-updates status through CI pipelines.
Overview
This example shows how an AI coding agent integrates with pm-cli to manage its own work session: orienting itself at startup, searching before creating, claiming tasks, linking evidence, and closing with validation results. It also covers a CI/CD pipeline that uses pm-cli to update task status automatically as builds and tests pass.
The key principles for agent use are:
- Always orient first โ run
pm context --jsonat the top of every session - Search before creating โ run
pm searchto avoid duplicating existing items - Claim before working โ
pm start-taskestablishes ownership and prevents double-work - Link evidence โ attach the files touched and test results via
pm files - Close with proof โ the closing reason should include measurable evidence
When to use this workflow
- An AI agent (Claude, Codex, or similar) is writing code and needs to coordinate with a human-maintained task list
- A CI/CD pipeline needs to automatically progress task status based on build results
- You want a machine-readable audit trail of what the agent touched and why
- Multiple agents may run concurrently and need to avoid claiming the same work
Key commands used
| Command | Purpose |
|---|---|
pm context --json |
Machine-readable project state at session start |
pm context --json --limit 10 |
Capped context snapshot (top 10 items per section) |
pm search "query" --json |
Find existing items before creating new ones |
pm create --json |
Create an item; parse the returned ID for use downstream |
pm start-task <id> --json |
Lifecycle alias: claim ownership and move to in_progress |
pm pause-task <id> --json |
Lifecycle alias: release claim and move back to open |
pm close-task <id> "reason" --json |
Lifecycle alias: close with reason and release assignment |
pm update <id> --json |
Update fields programmatically |
pm comments <id> "text" |
Record agent reasoning and intermediate results |
pm files <id> --add |
Attach files the agent read or modified |
pm test <id> --add |
Link a test command to the task |
pm test <id> --run |
Run linked test commands and record results |
pm docs <id> --add |
Attach spec or doc references |
pm activity --id <id> --limit 20 |
Review recent history on a specific item |
pm test-all --background --progress |
Run linked tests in background with live progress |
pm validate --json |
Check structural integrity after changes |
pm health --json |
Machine-readable health check |
Environment variable
Set PM_AUTHOR to the agent's identity so every action is attributed correctly in the
audit trail. In a multi-agent setup each agent has a distinct PM_AUTHOR.
export PM_AUTHOR="agent/claude-sonnet" # or "ci/github-actions", "agent/codex", etc.
Progressive context controls
pm context supports a --limit flag that controls how many items appear per section
in the snapshot. Use this to trade breadth for token efficiency as the session narrows.
--limit: control row depth per section
# Full view โ good for morning orientation or when switching domains
pm context --json
# Capped view โ top 10 items per section, keeps output concise mid-session
pm context --json --limit 10
# Minimal snapshot โ top 5 items, useful when you already know your task
pm context --json --limit 5
All three variants return the same JSON shape. --limit only controls how many rows
appear in each section (in_progress, open_high_priority, agenda, etc.).
Combining --limit with filters
Use filters alongside --limit to focus the snapshot further:
# Only show items assigned to this agent, top 5 per section
pm context --json --limit 5 --assignee "$PM_AUTHOR"
# Only show high-priority items
pm context --json --limit 10 --priority 1
Recommended pattern for agent sessions
# Step 1: broad orientation at session start
CONTEXT=$(pm context --json --limit 10)
echo "$CONTEXT" | jq '.in_progress, .open_high_priority'
# Step 2: if resuming a prior item, check its recent activity
RESUME_ID=$(echo "$CONTEXT" | jq -r \
--arg author "$PM_AUTHOR" \
'.in_progress[] | select(.owner == $author) | .id' | head -1)
if [ -n "$RESUME_ID" ]; then
pm activity --id "$RESUME_ID" --limit 20
fi
# Step 3: mid-session quick check (already know your item)
pm context --json --limit 5
Step-by-step narrative
1. Agent session startup โ orient with context
The very first thing an agent does is call pm context --json and parse the result.
This tells it: what is in progress (potentially its previous session), what is open and
highest priority, and whether anything is blocked.
export PM_AUTHOR="agent/claude-sonnet"
CONTEXT=$(pm context --json --limit 10)
echo "$CONTEXT" | jq '.in_progress, .open_high_priority'
If there is an in_progress item owned by this agent from a prior session, the agent
should resume it rather than starting something new.
2. Search before creating
Before creating a new task, the agent searches to avoid duplicating existing work.
pm search "add retry logic to HTTP client" --json | jq '.items'
If a matching item already exists, the agent claims and works it. Only if no match exists does the agent create.
3. Create items with JSON output for ID capture
When the agent does create an item, it uses --json to capture the assigned ID without
parsing human-readable TOON output.
TASK_ID=$(pm create \
--title "Add exponential backoff to HTTP client" \
--description "Retry failed requests up to 3 times with jitter. Affects src/http/client.ts" \
--type Task \
--priority 2 \
--json | jq -r '.id')
echo "Created task: $TASK_ID"
4. Claim the task
Use the pm start-task lifecycle alias, which combines claim + status transition in one step:
pm start-task "$TASK_ID" --json | jq '{id, status, owner}'
The agent verifies that status == "in_progress" and owner == PM_AUTHOR before
proceeding. If the claim fails (another agent beat it), the agent picks the next item.
To release a task without closing it (e.g. agent is interrupted), use pm pause-task:
pm pause-task "$TASK_ID" --json # moves back to open, releases owner
5. Record reasoning and intermediate state
As the agent works, it leaves comments explaining its reasoning. This is the machine equivalent of a commit message โ it answers "why did the agent make this choice?"
pm comments "$TASK_ID" \
"AGENT REASONING: Analyzed HTTP client. Current retry logic is a simple fixed delay (500ms). Changing to exponential backoff: delay = min(base * 2^attempt + jitter, max_delay). Base=100ms, max=10s, jitter=random(0,100ms). This matches AWS SDK retry behavior."
pm comments "$TASK_ID" \
"FILES MODIFIED: src/http/client.ts (retry logic), src/http/backoff.ts (new helper), tests/http/client.test.ts (6 new test cases)"
6. Attach files touched
pm files "$TASK_ID" --add path=src/http/client.ts,scope=project
pm files "$TASK_ID" --add path=src/http/backoff.ts,scope=project
pm files "$TASK_ID" --add path=tests/http/client.test.ts,scope=project
7. Link and run tests
Use pm test --add to link a test command to the task, then pm test --run to execute it.
This creates a permanent record that the task has verified tests.
# Link a test command to the task
pm test "$TASK_ID" --add command="npx vitest run tests/http/client.test.ts",scope=project,timeout_seconds=60
# Run the linked tests and show progress
pm test "$TASK_ID" --run --progress
8. Close with evidence
Use the pm close-task lifecycle alias, which records the reason and releases
assignment metadata in one step. Include measurable evidence so human reviewers
can validate the agent's work without re-running tests.
pm close-task "$TASK_ID" \
"Implemented exponential backoff with jitter in src/http/backoff.ts. 6 new unit tests added (all pass). Manual test: 3 retries on 503 response, delays were 147ms, 312ms, 891ms (matches expected distribution). PR #77 opened."
9. Run validation after session
pm validate --json | jq '.errors'
pm health --json | jq '.warnings'
The agent checks that it has not left any structural problems (orphaned items, invalid status transitions) before ending its session.
CI/CD Integration
GitHub Actions: update task status on build events
The workflow below is triggered on pull request events. It uses PM_AUTHOR=ci/github-actions
to attribute CI updates separately from human and agent actions.
See github-actions-example.yml in this directory for the full YAML.
The CI pipeline:
- On PR open โ adds a comment to the linked task with the PR URL
- On CI pass โ progresses the task to reflect passing tests
- On merge โ closes the task with build evidence
Linking a PR to a task
Include the task ID in the PR title or body (e.g. [APP-42]), then the CI script
can extract it and update the task.
# In CI: extract task ID from PR title
TASK_ID=$(echo "$PR_TITLE" | grep -oE '[A-Z]+-[0-9]+' | head -1)
if [ -n "$TASK_ID" ]; then
PM_AUTHOR=ci/github-actions pm comments "$TASK_ID" \
"CI: PR #${PR_NUMBER} opened. Build: ${BUILD_URL}"
fi
Show complete workflow script
#!/usr/bin/env tsx
import { execFileSync } from "node:child_process";
function pm(args: string[]): string {
const stdout = execFileSync("pm", args, { encoding: "utf8" });
process.stdout.write(stdout);
return stdout;
}
const query = process.env.PM_AGENT_QUERY ?? "failing CI";
const taskId = process.env.PM_TASK_ID;
pm(["context", "--json", "--depth", "full"]);
pm(["search", "--mode", "hybrid", query, "--json"]);
if (taskId) {
pm(["start-task", taskId, "--json"]);
pm(["test", taskId, "--add", "--command", process.env.PM_TEST_COMMAND ?? "npm test", "--description", "CI verification command"]);
pm(["test", taskId, "--run", "--json"]);
pm(["docs", taskId, "--add", "path=.github/workflows/ci.yml,scope=project,note=CI workflow under investigation"]);
pm(["comments", taskId, "Agent CI pass completed. Linked evidence and test command are attached."]);
} else {
pm([
"create",
"--type",
"Task",
"--title",
"Investigate CI failure",
"--description",
"Created by agent CI workflow after context and hybrid search.",
"--priority",
"1",
"--tags",
"agent,ci",
]);
}