Can now send chain-of-thought messages Manage terminals Control agent working directory Adding more tool support and notifications Some session management Added image support Added slash commands
7.7 KiB
Honker ACP Bridge — Implementation Plan
Current State
What's implemented today:
- ✅ Initialize ACP connection to Goose (
goose acpover stdio) - ✅ Create new sessions (one per Signal contact)
- ✅ Send text prompts and collect text responses
- ✅ Interactive permission requests over Signal (numbered options)
- ✅ Signal-cli lifecycle management and socket communication
Phase 1: Essential — Make the Bridge Robust
1.1 Terminal Execution (Client ← Agent)
Priority: HIGH — Goose cannot function without this
Goose's primary tool is running shell commands. The ACP protocol has the agent
ask the client to execute commands via create_terminal, then polls output
with terminal_output and wait_for_terminal_exit.
Currently we return None for all terminal methods, which means Goose can't
run any commands. We need to:
create_terminal(command, args, cwd, env)→ spawn a real subprocess, return aterminal_idterminal_output(terminal_id)→ return accumulated stdout/stderrwait_for_terminal_exit(terminal_id)→ await process completion, return exit coderelease_terminal(terminal_id)→ clean upkill_terminal(terminal_id)→ kill the subprocess
Implementation: a TerminalManager class that tracks running subprocesses
keyed by terminal_id.
1.2 File System Operations (Client ← Agent)
Priority: HIGH — Goose cannot edit code without this
The agent asks the client to read/write files:
read_text_file(path, line, limit)→ read from the local filesystem, return contentwrite_text_file(path, content)→ write to the local filesystem
Currently we return None, so Goose can't read or write files.
These should be straightforward to implement against the local filesystem.
We should also advertise these capabilities in ClientCapabilities during
initialize:
ClientCapabilities(
fs=FileSystemCapabilities(read_text_file=True, write_text_file=True),
terminal=True,
)
1.3 Cancellation
Priority: MEDIUM
Allow Signal users to cancel a running prompt. The user could send a special
command (e.g. /cancel) while a prompt is in progress. We'd call
conn.cancel(session_id) to tell Goose to stop.
The PromptResponse.stop_reason already distinguishes cancelled from
end_turn, max_tokens, refusal, and max_turn_requests — we should
handle each appropriately in the reply.
1.4 Stop Reason Handling
Priority: MEDIUM
Currently we only look at the response text. We should handle all stop reasons:
end_turn— normal completion (current behavior)max_tokens— context limit hit; notify usermax_turn_requests— agent hit its turn limit; notify userrefusal— agent refused the request; notify usercancelled— user cancelled; acknowledge
Phase 2: Enriched Feedback
2.1 Tool Call Notifications
Priority: MEDIUM
Forward tool activity as status messages so the Signal user knows what Goose
is doing while working. On ToolCallStart, send a brief message like:
"🔧 Running: ls -la /src"
On ToolCallProgress with status updates, optionally send progress. We need
to be careful not to spam — batch or throttle these.
2.2 Agent Thoughts
Priority: LOW-MEDIUM
AgentThoughtChunk contains the agent's chain-of-thought reasoning. Could
forward these optionally (config flag) as italicized or prefixed messages.
Useful for debugging but noisy for everyday use.
2.3 Plan Updates
Priority: LOW-MEDIUM
AgentPlanUpdate sends a structured plan with entries (content, priority,
status). Could render as a checklist:
📋 Plan:
✅ Read the project structure
🔄 Implement the new feature
⬚ Write tests
⬚ Update documentation
2.4 Usage/Cost Updates
Priority: LOW
UsageUpdate reports token usage (size, used) and optional Cost (amount,
currency). Could send periodic summaries or on-demand via a /usage command.
Phase 3: Session Management
3.1 Session Persistence (Load/Resume)
Priority: MEDIUM
Goose supports load_session and resume_session. We could persist the
session_id→contact mapping in SQLite (as the README mentions) and restore
sessions across honker restarts.
load_session(cwd, session_id)— restore conversation historyresume_session(cwd, session_id)— resume an interrupted sessionlist_sessions()— list available sessionsclose_session(session_id)— explicitly end a session
User commands: /sessions, /load <id>, /new (force new session)
3.2 Session Commands
Priority: MEDIUM
Signal user sends special commands (prefix with /):
/new— start a fresh session/sessions— list previous sessions/load <id>— resume a previous session/cancel— cancel current prompt/mode <mode>— change session mode (viaset_session_mode)/model <model>— change model (viaset_session_model)/usage— show token usage / cost
3.3 Session Modes
Priority: LOW
Goose supports modes (e.g., "auto" vs "manual" approval). set_session_mode
and CurrentModeUpdate notifications. Could expose via /mode command.
3.4 Session Configuration
Priority: LOW
set_config_option lets the client change boolean/select config options.
ConfigOptionUpdate notifications report changes. Could expose via a
/config command.
Phase 4: Rich Content
4.1 Image Support (Input)
Priority: MEDIUM
Signal users can send images. signal-cli provides attachment data. ACP
supports ImageContentBlock in prompts (with base64 data and mime_type).
We could forward Signal image attachments to Goose as image content blocks.
4.2 Image Support (Output)
Priority: LOW
If Goose responds with ImageContentBlock in agent messages, we could send
them as Signal attachments. Less common but possible.
4.3 File/Resource Content
Priority: LOW
ResourceContentBlock and EmbeddedResourceContentBlock in agent messages.
Could send file contents as Signal attachments or inline code blocks.
4.4 Audio Support
Priority: LOW
ACP has AudioContentBlock. Signal supports voice messages. Theoretically
bridgeable but Goose doesn't currently use audio.
Phase 5: Advanced / Optional
5.1 Multi-User Concurrency
Priority: MEDIUM
Currently each contact gets their own session, and prompts run as async tasks. But there's no protection against a user sending a second message while the first is still processing. Options:
- Queue messages per-user (process sequentially)
- Allow concurrent prompts (may confuse Goose session state)
- Tell the user "please wait" if a prompt is in progress
5.2 Group Messaging
Priority: LOW
Signal groups could map to shared Goose sessions. Would need the account number (already in config) for group message handling. signal-cli has different envelope structure for group messages.
5.3 Extension Methods
Priority: LOW
ext_method and ext_notification are catch-alls for custom protocol
extensions. Log them for now; implement specific ones if Goose uses them.
5.4 MCP Server Configuration
Priority: LOW
new_session accepts mcp_servers to connect external tool servers. Could
be configured per-contact or globally in honker config.
Decisions Made
- Terminal execution: Permission gate is enough. No additional sandboxing.
- Tool call notifications: Light — send "🔧 Running: ..." on tool start.
Goose already keeps extensive logs at
~/.local/state/goose/logs/. - Agent thoughts: Opt-in via config flag (
forward_thoughts: true). - Cancellation UX:
/cancelplus general/commandprefix convention. - Multi-user concurrency: "Please wait" — reject concurrent prompts per user.
- Image attachments: Yes, wire up in Phase 1.
- Working directory: Global config option (
working_directory).