What's Changed
Added
- Direct tool-run API for IDE clients (no LLM loop):
POST /api/tools/run,GET /api/tools/run/{job_id},DELETE /api/tools/run/{job_id}(cancel + SAQ abort),GET /api/tools/run-allowlist. Allowlisted tools (linter_run,test_runner, docker/git helpers, …) route viatool_routing.yamlto the native tools worker (SAQ) or run in-process. Configtools_run.allowed_toolsplusAGENTFORGE_TOOLS_RUN_ALLOW/AGENTFORGE_TOOLS_RUN_DENY. See docs/api.md and docs/tools.md - Playbooks: curated command-combinations + Jinja2 output templates for
@discover. Registryplaybooks.yaml+ templates undermarkdown/playbooks/*.jinja, retrieved semantically from a dedicated Qdrant collection (agentforge_playbooks, threshold-gated). A match seeds the investigation's probe commands and replaces LLM scoping (single pass,skip_analysis), and the rendered template pre-structures the synthesis input. Per-playbooksynthesis: diagnostic|informationalpicks the cleanup-plan or descriptive-report prompt. CLI:python -m agentforge.playbooks.cli reindex|list|match. Config underplaybooks.* - Recap:
POST /api/sessions/{id}/recapreturns a cumulative running summary of a session. Only messages after the previous recap are read (itssequenceis the watermark) and the previous recap text seeds the prompt, so the summary covers the whole session at incremental cost. Persisted as a volatilerecapmessage so it survives reloads without entering model context. Idle-safe: fewer thanrecap.min_new_messages(default 2) or no new messages returns the previous recap with no LLM call. Config underrecap.* @rebaseskill (markdown/skills/git-rebase.md): drives the local rebase-onto-default-branch flow, proposes per-file conflict resolutions and waits for approval, and enforces--force-with-lease(never bare--force, never the default branch)- AgentForge Email knowledge collection:
knowledge.mail_collection_name(kb_mail_entries), allowed viaX-Knowledge-Collection/ sessionsource=mail. Search acceptsprojects: [...](MatchAny) for multi-account All Inboxes filtering - JetBrains / IntelliJ custom-agent prompt (
markdown/custom-agents/intellij.md) for IDE-context agent runs
Changed
- Session compaction and recap share one conversation flattener (
web/server/summarise.py) instead of each carrying its own copy Dockerfile.webshipsplaybooks.yamlalongsideskills.yaml- New dependency:
jinja2(playbook templates) linter_run: multi-tool quality groups (ruff/flake8, black/isort checks, …);tool_name=black|isort|flake8|mypy|…resolves via a built-in known-tool map when missing from config; improved--fixfor black/isort- Secret redaction: high-entropy catch-all defaults off (fewer CamelCase false positives); skip pure CamelCase / snake_case identifiers when HE is on; clearer
SECRET_REDACTION_ENABLEDforce on/off; compose + native tools-worker launchd plist default redaction off for whole-file coding paths deploy-remote.shhealth probes: retry loop, web checks/api/health(not/), correct compose container name prefix, non-fatal SSH/health failures so the Done banner still prints
Fixed
- Command policy store no longer migrates on the shell/SSH hot path. Opening the chat DB ran
create_tables()(a full Alembic upgrade) on every command, which serialised each one behind a SQLite write-lock upgrade (journal_mode=DELETE) and deadlocked when the native worker and the web container shareweb_chat.db. A genuinely missing table is now repaired lazily byget_runtime_override; YAML policy stays authoritative either way @discoverno longer double-persistsdiscovery.plan(plan widget rendered twice on session reload)
Full changelog: https://github.com/bulletinmybeard/agent-forge/blob/master/CHANGELOG.md