You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
graff-agent is a new, separate repo that turns the existing graff binary into a Hermes-class personal agent — self-improving, multi-platform, scheduled, runtime-pluggable. It does this by depending on @codegraff/sdk (the N-API package on release/0.1.53) from npm and adding the surface area Hermes has and we don't.
This issue lives in codegraff because the prerequisite work is here: a small set of SDK additions need to ship before the new repo is buildable. Once those land, graff-agent proceeds independently.
Hermes inventory (full deep dive)
Sourced from a structured pass over the hermes-agent wiki — every line below is a real subsystem with concrete file paths.
1. Agent core
AIAgent class in run_agent.py — the central orchestrator. AIAgent.run_conversation() is the main loop.
Provider/model resolution in hermes_cli/runtime_provider.py.
Auxiliary LLM client (agent/auxiliary_client.py) for vision, summarization, web extraction — i.e. side tasks use a cheap model.
2. Skills system (agentskills.io compatible)
70+ bundled skills, optional skills hub.
skill_manage tool with actions create, patch, edit, write_file, delete, remove_file (see acp_adapter/tools.py).
Skills live under ~/.hermes/skills/<name>/ with SKILL.md + optional references/, templates/, scripts/ — same layout we already use under .forge/skills/.
3. Closed learning loop (the differentiator)
Autonomous skill creation: triggered after skills.creation_nudge_interval tool-calling iterations. Agent calls skill_manage action=create and writes to ~/.hermes/skills/.
Skill self-improvement during use: triggered when user corrects style/workflow or a non-trivial technique emerges. Priority order: patch loaded skill → update umbrella skill → add support file under umbrella → create new umbrella. Patches use old_string/new_string.
Cold-start vs warm-start prompt strategies based on prior session existence.
5. Messaging gateway
GatewayRunner in gateway/run.py — long-running daemon, started/stopped via hermes gateway start|stop.
BasePlatformAdapter in gateway/platforms/base.py defines the contract. Required: connect, disconnect, send, send_typing, get_chat_info. Optional: send_document, send_voice, send_image_file, etc.
Adapters: telegram.py, discord.py, slack.py, plus WhatsApp, Signal, Email.
Session keys:agent:main:{platform}:{chat_type}:{chat_id}, built via gateway/session.build_session_key().
Per-user group sessions:group_sessions_per_user (default true) — each sender in a group gets isolated state.
State persistence: SQLite (~/.hermes/state.db) for metadata + JSONL transcripts in ~/.hermes/sessions/.
Streaming: progressive message edits when platform supports it (SUPPORTS_MESSAGE_EDITING), driven by streaming.transport: edit.
Voice: auto-TTS gated by voice.auto_tts + per-chat /voice on|off|tts.
6. Cron scheduler
cron/jobs.py + cron/scheduler.py.
Jobs stored as JSON, support multiple schedule formats, can attach skills and scripts, deliver to any platform.
7. Subagent / parallelization
delegate_task tool spawns isolated subagents that share parent's iteration budget (no runaway loops).
execute_code tool: agent writes Python that calls Hermes tools via RPC — collapses multi-step pipelines into a single inference call.
8. Seven terminal backends
All implement BaseEnvironment ABC under tools/environments/.
Backends: LocalEnvironment, DockerEnvironment, SSHEnvironment, SingularityEnvironment, ModalEnvironment, plus Daytona and Vercel Sandbox.
Selection driven by terminal.backend in ~/.hermes/config.yaml (or TERMINAL_ENV env var). _get_env_config() + _create_environment() in tools/terminal_tool.py.
Trajectory recording substrate for evaluation and RL training.
10. Provider/model routing
hermes_cli/runtime_provider.py resolves provider + model with cost/speed/quality preferences.
Supports Nous Portal, OpenRouter, OpenAI, NVIDIA NIM, MiniMax, Kimi, z.ai, Hugging Face, custom endpoints.
11. Plugin system
Four discovery sources: bundled (<repo>/plugins/), user (~/.hermes/plugins/), project (./.hermes/plugins/ if HERMES_ENABLE_PROJECT_PLUGINS=1), and pip entry points (hermes_agent.plugins).
PluginManager in hermes_cli/plugins.py runs discover_and_load(). Later sources override earlier on collision.
User-profile API — graff.user.facts.{list, upsert, delete}.
Recall API — graff.search.recall(query, opts): Promise<RecallHit[]> over the FTS5 table.
Context-engine + memory-provider hooks — register-time interface so a memory provider (e.g. graff-honcho) can inject system-prompt context every turn (onSystemPromptAssemble).
Lifecycle hooks — onPreToolCall, onPostToolCall, onPreLLMCall, onPostLLMCall, onSessionStart, onSessionEnd. Sidecars subscribe; this is the minimal plugin system Part 1.
A.2 — Backing changes in forge_app / forge_repo
pending_nudges table + poll point in the conversation loop.
user_profile table.
FTS5 virtual table over trajectory_events (or a derived messages table) + diesel migration.
MemoryProvider trait in forge_domain + injection point in system-prompt assembly (mirrors Hermes' Layer-3 Honcho block).
ExecutionEnvironment trait + Local impl. (Docker/SSH/Modal/etc. land in graff-agent.)
memory/manager.ts — owns MEMORY.md, USER.md files in ~/.graff/
Loop: subscribe to trajectory events → on TaskComplete, run review prompt via runAgent({ model: cheapModel }) → if agent calls skill mutation tools, they hit the SDK API → on cron tick, inject pending_nudges for review prompts.
Phase 5 — More platforms (Discord, Slack, WhatsApp, Signal, Email)
Phase 6 — graff-honcho memory provider
Phase 7 — graff-runtimes (Docker first, then SSH, then sandbox providers)
Phase 8 — execute_code tool, ACP server (parallel tracks once core lands)
Open questions (carried)
graff-memd language: TS via SDK (consistency, faster iteration) vs Rust (zero N-API overhead, direct DB). Default: TS. Rewrite later if profiling demands.
Skill format: stay 100% on agentskills.io spec, or extend with version + confidence for the self-improvement loop? Decide when skill mutation API lands.
Memory provider activation: only-one-active (Hermes' rule) vs stacked? Mirror Hermes for now.
Should the gateway's per-platform SQLite live in ~/.graff/ or share @codegraff/sdk's DB? Probably separate, joined by conversation_id.
Out of scope here
Copying Hermes code — graff-agent is an independent re-implementation atop graff.
RL trajectory generation / Atropos environments — recording substrate exists; training is its own workstream.
Building any graff-agent package in this issue — that work happens in the new repo. This issue tracks only Part A.
Sub-issues (filed)
Tracked here for execution order. All target release/0.1.53.
P0 — substrate (do first; everything else depends on these)
Thesis
graff-agentis a new, separate repo that turns the existinggraffbinary into a Hermes-class personal agent — self-improving, multi-platform, scheduled, runtime-pluggable. It does this by depending on@codegraff/sdk(the N-API package onrelease/0.1.53) from npm and adding the surface area Hermes has and we don't.This issue lives in
codegraffbecause the prerequisite work is here: a small set of SDK additions need to ship before the new repo is buildable. Once those land,graff-agentproceeds independently.Hermes inventory (full deep dive)
Sourced from a structured pass over the hermes-agent wiki — every line below is a real subsystem with concrete file paths.
1. Agent core
AIAgentclass inrun_agent.py— the central orchestrator.AIAgent.run_conversation()is the main loop.hermes_cli/runtime_provider.py.agent/auxiliary_client.py) for vision, summarization, web extraction — i.e. side tasks use a cheap model.2. Skills system (agentskills.io compatible)
skill_managetool with actionscreate,patch,edit,write_file,delete,remove_file(seeacp_adapter/tools.py).~/.hermes/skills/<name>/withSKILL.md+ optionalreferences/,templates/,scripts/— same layout we already use under.forge/skills/.3. Closed learning loop (the differentiator)
skills.creation_nudge_intervaltool-calling iterations. Agent callsskill_manage action=createand writes to~/.hermes/skills/.old_string/new_string._MEMORY_REVIEW_PROMPT,_SKILL_REVIEW_PROMPT,_COMBINED_REVIEW_PROMPTinjected periodically insideAIAgent(run_agent.py)._summarize_background_review_actionsproduces user-facing summaries.~/.hermes/state.dbwith FTS5 over conversation content.session_searchtool. Summarization step uses Gemini Flash.MEMORY.mdandUSER.mdorchestrated byagent/memory_manager.py.4. User modeling — Honcho
plugins/memory/honcho/implementing theMemoryProviderABC.contextCadence) + dialectic LLM layer (dialecticCadence).honcho_profile,honcho_search,honcho_context,honcho_reasoning,honcho_conclude.5. Messaging gateway
GatewayRunneringateway/run.py— long-running daemon, started/stopped viahermes gateway start|stop.BasePlatformAdapteringateway/platforms/base.pydefines the contract. Required:connect,disconnect,send,send_typing,get_chat_info. Optional:send_document,send_voice,send_image_file, etc.telegram.py,discord.py,slack.py, plus WhatsApp, Signal, Email.agent:main:{platform}:{chat_type}:{chat_id}, built viagateway/session.build_session_key().group_sessions_per_user(defaulttrue) — each sender in a group gets isolated state.~/.hermes/state.db) for metadata + JSONL transcripts in~/.hermes/sessions/.SUPPORTS_MESSAGE_EDITING), driven bystreaming.transport: edit.voice.auto_tts+ per-chat/voice on|off|tts.6. Cron scheduler
cron/jobs.py+cron/scheduler.py.7. Subagent / parallelization
delegate_tasktool spawns isolated subagents that share parent's iteration budget (no runaway loops).execute_codetool: agent writes Python that calls Hermes tools via RPC — collapses multi-step pipelines into a single inference call.8. Seven terminal backends
BaseEnvironmentABC undertools/environments/.LocalEnvironment,DockerEnvironment,SSHEnvironment,SingularityEnvironment,ModalEnvironment, plus Daytona and Vercel Sandbox.terminal.backendin~/.hermes/config.yaml(orTERMINAL_ENVenv var)._get_env_config()+_create_environment()intools/terminal_tool.py.9. Trajectory recording + Atropos RL
environments/hermes_base_env.py—HermesAgentBaseEnvextends AtroposBaseEnv.10. Provider/model routing
hermes_cli/runtime_provider.pyresolves provider + model with cost/speed/quality preferences.11. Plugin system
<repo>/plugins/), user (~/.hermes/plugins/), project (./.hermes/plugins/ifHERMES_ENABLE_PROJECT_PLUGINS=1), and pip entry points (hermes_agent.plugins).PluginManagerinhermes_cli/plugins.pyrunsdiscover_and_load(). Later sources override earlier on collision.register(ctx):pre_tool_call,post_tool_call,pre_llm_call,post_llm_call,on_session_start,on_session_end.ctx.register_tool(...).ctx.register_cli_command(...).MemoryProvider(only one active), context engines (only one active).12. Other notable subsystems
agent/context_compressor.pysummarizes turns near limits.agent/prompt_caching.pyapplies Anthropic cache breakpoints.acp_adapter/exposes Hermes as IDE-native agent over stdio/JSON-RPC for VS Code, Zed, JetBrains.What this repo (codegraff) has today
crates/forge_app/src/agent_executor.rs,app.rscrates/forge_app/src/dto/{anthropic,google,openai}/crates/forge_infra(paginated tools, structured results)crates/codegraff-tui/src/main.rs(~7900 LOC)forge_app/src/trajectory_recorder.rs,forge_repo/src/trajectory//trace,/resumeforge_domain/src/skill.rs,forge_services/src/tool_services/skill.rs,.forge/skills/forge_app/src/compact.rs(931 LOC)release/0.1.53)sdk/typescript/forge_main/src/main.rs(-p, stdin,--conversation-id)forge_main/src/cli.rs(conversation dump/show)Gap analysis — Hermes vs codegraff today
MEMORY.md/USER.mdfilesagent:main:{platform}:{chat_type}:{chat_id})delegate_taskparallelismexecute_codetool (Python RPC into agent tools)Two repos, clear separation
Why split:
graff-agentdevelopers don't need a Rust toolchain —npm installpulls prebuilt N-API binaries.codegraffkeeps shipping the core and SDK on its own cadence;graff-agentships gateway/cron/memd independently.Part A — work that lands in
codegraff(this repo)These are the prerequisites that make
graff-agentbuildable. Each becomes a follow-up issue.A.1 — SDK additions (
sdk/typescript/src/lib.rs+wire.rs)graff.trajectory.subscribe(conversationId): AsyncIterable<TrajectoryEvent>. Tokio broadcast → N-API ThreadsafeFunction.graff.skills.create | update | patch | writeFile | delete | removeFile. Mirrors Hermes'skill_manageactions exactly.graff.conversations.compact(cid): Promise<Digest>reusingforge_app/src/compact.rs.graff.nudges.enqueue(cid, message).graff.user.facts.{list, upsert, delete}.graff.search.recall(query, opts): Promise<RecallHit[]>over the FTS5 table.onSystemPromptAssemble).onPreToolCall,onPostToolCall,onPreLLMCall,onPostLLMCall,onSessionStart,onSessionEnd. Sidecars subscribe; this is the minimal plugin system Part 1.A.2 — Backing changes in
forge_app/forge_repopending_nudgestable + poll point in the conversation loop.user_profiletable.trajectory_events(or a derivedmessagestable) + diesel migration.MemoryProvidertrait inforge_domain+ injection point in system-prompt assembly (mirrors Hermes' Layer-3 Honcho block).ExecutionEnvironmenttrait +Localimpl. (Docker/SSH/Modal/etc. land ingraff-agent.)SkillRepository::write,delete,patch). YAML frontmatter parsing for progressive disclosure.A.3 — Release
npm publishstep in.github/workflows/sdk-typescript.yml(CI already builds the matrix; assemble job stops short of publish).@codegraff/sdk@0.2.0.A.4 —
graffCLI surface (small)graff conversation export <cid>→ JSONL transcript (Hermes-style~/.hermes/sessions/).graff doctorfor environment + provider sanity (Hermes parity).Part B —
graff-agentrepo (new, future)Layout once Part A ships:
B.1 —
graff-memd(closed learning loop)Mirrors Hermes' nudge + review system, file-by-file analog:
_MEMORY_REVIEW_PROMPTinrun_agent.pypackages/graff-memd/src/prompts/memory-review.ts_SKILL_REVIEW_PROMPTprompts/skill-review.ts_COMBINED_REVIEW_PROMPTprompts/combined-review.ts_summarize_background_review_actionsdigest/summarize.tsagent/context_compressor.pygraff.conversations.compact()from SDKagent/memory_manager.pymemory/manager.ts— ownsMEMORY.md,USER.mdfiles in~/.graff/Loop: subscribe to trajectory events → on
TaskComplete, run review prompt viarunAgent({ model: cheapModel })→ if agent calls skill mutation tools, they hit the SDK API → on cron tick, injectpending_nudgesfor review prompts.B.2 —
graff-gatewayDirect port of Hermes'
gateway/:PlatformAdapterabstract (matches Hermes'BasePlatformAdapter).agent:main:{platform}:{chat_type}:{chat_id}.~/.graff/gateway.dbfor(platform, chat_id) → conversation_idmapping; main conversation state stays in@codegraff/sdk's SQLite.B.3 —
graff-cron~/.graff/cron/jobs.json(Hermes uses JSON not TOML — match for portability).skill: <name>+script: <path>+delivery: {platform, chat_id}.~/.graff/cron/runs/<job_id>/<run_id>.jsonl.B.4 —
graff-honchoMemoryProvidertrait (added in Part A) via the SDK plugin hooks.honcho_profile,honcho_search,honcho_context,honcho_reasoning,honcho_conclude.B.5 —
graff-runtimesExecutionEnvironment(matches the codegraff Rust trait, talks to it via SDK).Docker,SSH,Singularity,Modal,Daytona,VercelSandbox. (Local stays in codegraff.)B.6 —
graff-agentCLIMirrors Hermes' top-level CLI:
graff-agent(start interactive) — actually shells out tografffor the TUI.graff-agent gateway start|stop|setupgraff-agent cron list|add|run|deletegraff-agent skills hub(community hub fetch)graff-agent doctorgraff-agent setup(full wizard)Roadmap
Phase 0 — codegraff Part A (this issue, broken into ~10 sub-issues)
Land all SDK + backing changes; cut
@codegraff/sdk@0.2.0to npm.Phase 1 —
graff-agentrepo bootstrapEmpty repo, pnpm workspaces, CI,
@codegraff/sdk@0.2.0integrated, smoke test.Phase 2 —
graff-memdv0MEMORY.md/USER.mdfilesPhase 3 —
graff-gatewayTelegram onlyPhase 4 —
graff-cronPhase 5 — More platforms (Discord, Slack, WhatsApp, Signal, Email)
Phase 6 —
graff-honchomemory providerPhase 7 —
graff-runtimes(Docker first, then SSH, then sandbox providers)Phase 8 —
execute_codetool, ACP server (parallel tracks once core lands)Open questions (carried)
graff-memdlanguage: TS via SDK (consistency, faster iteration) vs Rust (zero N-API overhead, direct DB). Default: TS. Rewrite later if profiling demands.version+confidencefor the self-improvement loop? Decide when skill mutation API lands.~/.graff/or share@codegraff/sdk's DB? Probably separate, joined byconversation_id.Out of scope here
graff-agentis an independent re-implementation atopgraff.graff-agentpackage in this issue — that work happens in the new repo. This issue tracks only Part A.Sub-issues (filed)
Tracked here for execution order. All target
release/0.1.53.P0 — substrate (do first; everything else depends on these)
skills.{create,update,patch,writeFile,delete,removeFile}messages_ftsvirtual table + SDKsearch.recallpending_nudgestable + conversation-loop poll point + SDKnudges.enqueueuser_factstable + SDKuser.facts.{list,upsert,get,delete}P1 — live data flow (graff-memd needs these to react in real time)
trajectory.subscribeconversations.compactP2 — extensibility (gateway / cron / memd / honcho / runtimes plug in here)
plugins.registerMemoryProviderexec.registerEnvironmentP3 — release gate
@codegraff/sdk@0.2.0P4 — CLI polish
graff conversation export <cid>(JSONL) +graff doctorOnce all of P0–P3 land and
@codegraff/sdk@0.2.0is on npm, the newgraff-agentrepo is unblocked and Phase 1 begins there.