Long-running task management plugin for Hermes Agent
Project description
SagTask
A Hermes Agent standalone user plugin for long-running, multi-phase tasks with structured methodology execution, subagent orchestration, and cross-session recovery. Each task gets its own Git repository with full version control.
SagTask is NOT a memory provider. It coexists with any memory system and injects task context via the
pre_llm_callhook.
Multi-Agent Collaboration
Hermes supports multiple profiles (agents) that share the same ~/.hermes/sag_tasks/ directory — all agents collaborate on the same pool of tasks. But each agent tracks its own active task independently:
~/.hermes/
├── plugins/sagtask/ ← Default profile plugin
├── profiles/
│ ├── hbuilder/plugins/sagtask/ ← Profile "hbuilder" plugin
│ └── hexpert/plugins/sagtask/ ← Profile "hexpert" plugin
└── sag_tasks/ ← Shared task pool (all agents)
├── .active_tasks.json ← Per-profile active task tracking
├── my-project/ ← Task Git repo (shared)
└── another-task/ ← Task Git repo (shared)
.active_tasks.json tracks which task each agent is working on:
{
"default": "my-project",
"hbuilder": "sagtask-devop",
"hexpert": null
}
How it works:
- Each profile's
SagTaskPluginderives its profile ID from the_hermes_homepath (~/.hermes/profiles/<name>) _active_task_idis a@propertythat transparently reads/writes the correct entry in the dict- Zero changes needed in handlers or hooks — the property abstraction handles everything
- Legacy
.active_taskfiles are auto-migrated on first read
Installation: install.sh and /sagtask update automatically install the plugin to all profiles:
curl -fsSL https://raw.githubusercontent.com/ethanchen669/sagtask/main/install.sh | bash
# Installs to ~/.hermes/plugins/sagtask/ + every ~/.hermes/profiles/*/plugins/sagtask/
Quick Install
curl -fsSL https://raw.githubusercontent.com/ethanchen669/sagtask/main/install.sh | bash
Or manually:
git clone https://github.com/ethanchen669/sagtask.git ~/.hermes/plugins/sagtask
# Restart your Hermes gateway to load the plugin
Self-Update
SagTask has a built-in /sagtask slash command:
/sagtask update → Check GitHub releases, download + install to all profiles
/sagtask version → Show current installed version
/sagtask help → Show usage
Tools (20)
Task Lifecycle
| Tool | Description |
|---|---|
sag_task_create |
Create task with phased steps/gates, init Git + GitHub repo |
sag_task_status |
Show current phase/step/pending gates |
sag_task_advance |
Move to next step/phase (blocks if verification fails) |
sag_task_pause |
Snapshot execution context for later resume |
sag_task_resume |
Restore from most recent paused execution |
sag_task_approve |
Submit approval decision for a pending gate |
sag_task_list |
List all tasks with status |
Planning & Execution
| Tool | Description |
|---|---|
sag_task_plan |
Generate structured subtask plan for the current step |
sag_task_plan_update |
Update subtask status (done/failed), sync progress |
sag_task_dispatch |
Build subagent context for a subtask, optional worktree isolation |
sag_task_verify |
Run verification commands, record pass/fail |
sag_task_review |
Build structured review prompt (step/phase/full scope) |
Methodology
| Tool | Description |
|---|---|
sag_task_brainstorm |
Design exploration → option selection workflow |
sag_task_debug |
Systematic debugging: reproduce → diagnose → fix |
sag_task_metrics |
Query verification stats, coverage trends, throughput |
Rules
| Tool | Description |
|---|---|
sag_task_rules |
Manage development rules: list/add/update/remove/toggle |
12 built-in rules auto-loaded on task creation. Smart context injection selects relevant rules based on methodology and phase.
Git Operations
| Tool | Description |
|---|---|
sag_task_commit |
Stage all + commit with message |
sag_task_branch |
Create + push new branch |
sag_task_git_log |
Show recent commit history |
sag_task_relate |
Link two tasks as cross-pollination partners |
Architecture
src/sagtask/
├── __init__.py ← register(), re-exports
├── plugin.py ← SagTaskPlugin class, layered context injection
├── hooks.py ← pre_llm_call, on_session_start
├── schemas.py ← 19 tool JSON schemas
├── _utils.py ← constants, shared helpers
└── handlers/
├── __init__.py ← _tool_handlers dispatch dict
├── _lifecycle.py ← create, status, advance, pause, resume, approve, list
├── _plan.py ← plan, plan_update, verify, brainstorm, debug
├── _orchestration.py← dispatch, review, context builders
├── _metrics.py ← metrics query handler
└── _git.py ← commit, branch, git_log, relate
Plugin Registration
register(ctx)
├── ctx.register_tool("sag_task_*", ...) × 19
├── ctx.register_hook("pre_llm_call", ...) # layered context injection
└── ctx.register_hook("on_session_start", ...) # restore active task
Context Injection — Layered System
SagTask injects a compact, adaptive context block before each LLM call. The system minimizes token usage by only including information that has changed or is urgently needed.
| Layer | Content | Frequency |
|---|---|---|
| L0 | [SagTask] task=X status=active phase=P step=S |
Every turn |
| L1 | Phase/step names, pending gates | On change + blocking gates |
| L1.5 | Artifacts summary | On change |
| L2 | Methodology phase, plan progress, failures | On change |
| L3 | Verification status, metrics (pass rate, coverage) | On change + blocking |
| L4a | Related tasks hint ("2 tasks available") | When relationships exist |
| L4b | Related task details | First turn, step switch, user intent |
Cache: Per-session per-task cache with context hashing. Stable state → single L0 line (~50 tokens). Changed state → relevant layers expand.
Methodology System
Each step can declare a methodology that guides execution:
| Type | Workflow |
|---|---|
tdd |
RED → GREEN → REFACTOR cycle, auto-transitions on verify |
brainstorm |
Generate 3+ options → user selects → implement |
debug |
Reproduce → diagnose (hypothesis) → fix |
plan-execute |
Plan subtasks → execute sequentially → verify each |
none |
No methodology constraint (default) |
Orchestration
sag_task_plan → Generate subtasks from step description
sag_task_dispatch → Build subagent context, optional git worktree
└─ subagent executes → sag_task_plan_update(status="done")
sag_task_review → Spec compliance + quality review context
sag_task_verify → Run commands, record results to metrics
sag_task_advance → Move to next step (blocks if must_pass fails)
Metrics
Append-only event log (.sag_metrics.jsonl) tracks:
- Verification runs (pass/fail, exit codes, coverage)
- Subtask completions
- Step advances, dispatches, pauses/resumes
Query with sag_task_metrics for pass rates, coverage trends, and subtask throughput.
Storage Layout
~/.hermes/sag_tasks/<task_id>/
├── .git/ ← Task Git repo
├── .gitignore
├── .sag_task_state.json ← Machine-readable state (git-ignored)
├── .sag_plans/ ← Subtask plans (git-tracked)
│ └── <step_id>.json
├── .sag_metrics.jsonl ← Metrics event log (git-ignored)
├── .sag_artifacts/ ← Generated artifacts (git-ignored)
├── .sag_executions/ ← Pause snapshots (git-ignored)
├── .sag_worktrees/ ← Isolated subtask worktrees (git-ignored)
└── src/, tests/, docs/ ← User code (git-tracked)
Development
# Run tests
python -m pytest tests/ -v
# Run with coverage
python -m pytest tests/ --cov=src/sagtask --cov-report=term-missing
# Install for local Hermes dev
./dev-install.sh
# Build release tarball
bash scripts/build-release.sh 2.0.0
# Bump version across all files
bash scripts/bump-version.sh 2.1.0
Release Process
bash scripts/bump-version.sh X.Y.Z
# Update CHANGELOG.md
git add -A && git commit -m "chore: release vX.Y.Z"
git tag vX.Y.Z && git push origin main --tags
# GitHub Actions builds artifact + creates release automatically
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sagtask-2.2.0.tar.gz.
File metadata
- Download URL: sagtask-2.2.0.tar.gz
- Upload date:
- Size: 45.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f6c9d40252bba0b9e679fbf4a7801d592584546eecd1b006ce193e1c617a7ace
|
|
| MD5 |
de3e7220cdedf24d6b7282fa12ec7013
|
|
| BLAKE2b-256 |
3303a25232ff46f113ab52c6f31b5f9c32287be86baeb29430470fa628c8125d
|
Provenance
The following attestation bundles were made for sagtask-2.2.0.tar.gz:
Publisher:
release.yml on ethanchen669/sagtask
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sagtask-2.2.0.tar.gz -
Subject digest:
f6c9d40252bba0b9e679fbf4a7801d592584546eecd1b006ce193e1c617a7ace - Sigstore transparency entry: 1708559755
- Sigstore integration time:
-
Permalink:
ethanchen669/sagtask@b61a9db562ac911fef9a82cc44da6259c9d13739 -
Branch / Tag:
refs/tags/v2.2.0 - Owner: https://github.com/ethanchen669
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b61a9db562ac911fef9a82cc44da6259c9d13739 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sagtask-2.2.0-py3-none-any.whl.
File metadata
- Download URL: sagtask-2.2.0-py3-none-any.whl
- Upload date:
- Size: 54.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0302af885fc9bc5a4d2c3bfaead6e315a2e159692c3f871532ad69949178c1b
|
|
| MD5 |
9a277813290f1eeab1ca822b77eb2c9d
|
|
| BLAKE2b-256 |
28357e41abb6d6b843104726b62e5334562df9fc6c430df247b05fa0b5e32617
|
Provenance
The following attestation bundles were made for sagtask-2.2.0-py3-none-any.whl:
Publisher:
release.yml on ethanchen669/sagtask
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sagtask-2.2.0-py3-none-any.whl -
Subject digest:
b0302af885fc9bc5a4d2c3bfaead6e315a2e159692c3f871532ad69949178c1b - Sigstore transparency entry: 1708559806
- Sigstore integration time:
-
Permalink:
ethanchen669/sagtask@b61a9db562ac911fef9a82cc44da6259c9d13739 -
Branch / Tag:
refs/tags/v2.2.0 - Owner: https://github.com/ethanchen669
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b61a9db562ac911fef9a82cc44da6259c9d13739 -
Trigger Event:
push
-
Statement type: