Summary
hermes acp's session/load handler returns immediately after refreshing cwd and registering MCP servers. It does not replay the session's past session_update notifications, which the ACP specification says the agent should do.
Repro
With any external ACP client (I'm using a TypeScript client built with @agentclientprotocol/sdk v0.19.0):
- Start a session with
newSession, run a prompt, collect the agent's tool-use + message notifications.
- Record the resulting
sessionId.
- Start a fresh ACP connection to a new
hermes acp subprocess.
- Call
loadSession({ sessionId, cwd, mcpServers: [] }).
- Observe the
Client.sessionUpdate callback.
Expected: a stream of session_update notifications replaying agent_message_chunk, tool_call, tool_call_update, etc. for the prior turns, then loadSession resolves.
Actual: exactly one available_commands_update notification (from _schedule_available_commands_update), then loadSession resolves. No conversation history is streamed.
Where in the code
acp_adapter/server.py:375-389 (hermes-agent v0.10):
async def load_session(self, cwd, session_id, mcp_servers, **kwargs):
state = self.session_manager.update_cwd(session_id, cwd)
if state is None:
logger.warning("load_session: session %s not found", session_id)
return None
await self._register_session_mcp_servers(state, mcp_servers)
logger.info("Loaded session %s", session_id)
self._schedule_available_commands_update(session_id)
return LoadSessionResponse(models=self._build_model_state(state))
The transcript itself is preserved on disk (~/.hermes/sessions/session_<session_id>.json) — it just isn't sent back over the protocol.
Spec reference
From Session Setup → Loading Sessions:
The agent should:
- Restore the session context and conversation history
- Connect to the specified MCP servers
- Stream the entire conversation history back to the client via notifications
Suggested fix
After the current body and before return, iterate the stored messages for this session and emit each as a session_update notification with the matching sessionUpdate kind (user_message_chunk, agent_message_chunk, tool_call, tool_call_update), then return LoadSessionResponse. The mapping from hermes's internal message format to ACP notifications already exists in the live prompt path — it just isn't invoked during load.
Why this matters
External ACP clients (editors, orchestrators) that reconnect to an existing session have no way to reconstruct the conversation. In our case, an agent dashboard that shows task history gets an empty panel whenever a hermes-backed session is re-opened, even though the data is intact on disk. Parsing ~/.hermes/sessions/*.json directly works as a workaround but defeats the point of the protocol boundary.
Environment
- hermes-agent v0.9.0 (Apr 13, 2026)
@agentclientprotocol/sdk v0.19.0
- macOS 14.6, Python 3.11.14
Happy to submit a PR if the fix shape above looks right.
Summary
hermes acp'ssession/loadhandler returns immediately after refreshing cwd and registering MCP servers. It does not replay the session's pastsession_updatenotifications, which the ACP specification says the agent should do.Repro
With any external ACP client (I'm using a TypeScript client built with
@agentclientprotocol/sdkv0.19.0):newSession, run a prompt, collect the agent's tool-use + message notifications.sessionId.hermes acpsubprocess.loadSession({ sessionId, cwd, mcpServers: [] }).Client.sessionUpdatecallback.Expected: a stream of
session_updatenotifications replayingagent_message_chunk,tool_call,tool_call_update, etc. for the prior turns, thenloadSessionresolves.Actual: exactly one
available_commands_updatenotification (from_schedule_available_commands_update), thenloadSessionresolves. No conversation history is streamed.Where in the code
acp_adapter/server.py:375-389(hermes-agent v0.10):The transcript itself is preserved on disk (
~/.hermes/sessions/session_<session_id>.json) — it just isn't sent back over the protocol.Spec reference
From Session Setup → Loading Sessions:
Suggested fix
After the current body and before
return, iterate the stored messages for this session and emit each as asession_updatenotification with the matchingsessionUpdatekind (user_message_chunk,agent_message_chunk,tool_call,tool_call_update), then returnLoadSessionResponse. The mapping from hermes's internal message format to ACP notifications already exists in the live prompt path — it just isn't invoked during load.Why this matters
External ACP clients (editors, orchestrators) that reconnect to an existing session have no way to reconstruct the conversation. In our case, an agent dashboard that shows task history gets an empty panel whenever a hermes-backed session is re-opened, even though the data is intact on disk. Parsing
~/.hermes/sessions/*.jsondirectly works as a workaround but defeats the point of the protocol boundary.Environment
@agentclientprotocol/sdkv0.19.0Happy to submit a PR if the fix shape above looks right.