- Go 99.3%
- Shell 0.7%
Move the project off the GitHub module identity to git.goclaw.org and update docs, examples, and fork-maintenance guidance to match the hard fork workflow. Made-with: Cursor |
||
|---|---|---|
| docs | ||
| internal/cmd/schema | ||
| schema | ||
| .gitignore | ||
| acp.go | ||
| acp_integration_test.go | ||
| acp_simple_test.go | ||
| agent.go | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| client.go | ||
| conn.go | ||
| errors.go | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| match.go | ||
| middleware.go | ||
| README.md | ||
| schema.ext.go | ||
| schema.gen.go | ||
| schema.gen.unstable.go | ||
| session_store.go | ||
| session_stream.go | ||
| session_update_ordering_test.go | ||
| terminal.go | ||
| terminal_test.go | ||
| transport.go | ||
| transport_http.go | ||
Agent Client Protocol - Go Implementation
A Go implementation of the Agent Client Protocol (ACP), which standardizes communication between code editors (interactive programs for viewing and editing source code) and coding agents (programs that use generative AI to autonomously modify code).
This is an unofficial implementation of the ACP specification in Go. The official protocol specification and reference implementations can be found at the official repository.
Note
The Agent Client Protocol is under active development. This implementation may lag behind the latest specification changes. Please refer to the official repository for the most up-to-date protocol specification.
Learn more about the protocol at agentclientprotocol.com.
Installation
go get git.goclaw.org/roelfdiedericks/acp-go
import acp "git.goclaw.org/roelfdiedericks/acp-go"
Example Code
See the docs/example directory for complete working examples:
- Agent Example - Agent implementation with SessionStream, middleware, and permission requests
- Client Example - Client implementation using SpawnAgent and MatchSessionUpdate
Architecture
This implementation provides a clean, modern architecture with bidirectional JSON-RPC 2.0 communication:
Connection: Unified bidirectional transport layer with concurrent request/response correlationTransport: Pluggable transport interface (stdio, HTTP+SSE) for flexible deploymentAgentSideConnection: High-level ACP interface for implementing agentsClientSideConnection: High-level ACP interface for implementing clientsSessionStream: Convenience wrapper for sending session updates with minimal boilerplateMiddleware: Composable request/response processing chain for cross-cutting concernsTerminalHandle: Resource management wrapper for terminal sessions- Generated Types: Complete type-safe Go structs generated from the official ACP JSON schema
Quick Start
Agent
agent := &MyAgent{}
conn := acp.NewAgentSideConnection(agent, os.Stdin, os.Stdout,
acp.WithMiddleware(acp.RecoveryMiddleware()),
acp.WithMiddleware(acp.LoggingMiddleware(nil)),
)
conn.Start(context.Background())
Client
client := &MyClient{}
conn, _ := acp.SpawnAgent(ctx, client, "my-agent")
go conn.Start(ctx)
conn.Initialize(ctx, &acp.InitializeRequest{...})
conn.Prompt(ctx, &acp.PromptRequest{...})
Features
Transport Layer
The SDK supports pluggable transports via the Transport interface:
// Default: stdio (newline-delimited JSON)
conn := acp.NewConnection(handler, os.Stdin, os.Stdout)
// HTTP+SSE transport for web deployments
transport := acp.NewHTTPServerTransport()
conn := acp.NewConnection(handler, nil, nil, acp.WithTransport(transport))
http.Handle("/", transport.Handler())
Middleware
Add cross-cutting concerns to the connection handler chain:
conn := acp.NewAgentSideConnection(agent, reader, writer,
acp.WithMiddleware(
acp.RecoveryMiddleware(), // catch panics
acp.LoggingMiddleware(log.Printf), // log method calls
acp.TimeoutMiddleware(30 * time.Second), // per-request timeout
),
)
Custom middleware follows the standard pattern:
func authMiddleware(next acp.MethodHandler) acp.MethodHandler {
return func(ctx context.Context, method string, params json.RawMessage) (any, error) {
if method != "initialize" && !isAuthenticated(ctx) {
return nil, acp.ErrAuthRequired(nil)
}
return next(ctx, method, params)
}
}
SessionStream
Reduce boilerplate when sending session updates from agents:
stream := acp.NewSessionStream(client, sessionID)
// Stream text
stream.SendText(ctx, "Hello!")
stream.SendThought(ctx, "thinking...")
// Tool call lifecycle
stream.StartToolCall(ctx, toolID, "Reading file", acp.ToolKindRead)
stream.CompleteToolCall(ctx, toolID, content...)
stream.FailToolCall(ctx, toolID)
// Other updates
stream.SendPlan(ctx, entries)
stream.SendModeUpdate(ctx, modeID)
stream.SendSessionInfo(ctx, title, updatedAt)
Match Pattern
Exhaustive pattern matching for discriminated union types:
acp.MatchSessionUpdate(&update, acp.SessionUpdateMatcher[string]{
AgentMessageChunk: func(v acp.SessionUpdateAgentMessageChunk) string {
return acp.MatchContentBlock(&v.Content, acp.ContentBlockMatcher[string]{
Text: func(t acp.ContentBlockText) string { return t.Text },
Default: func() string { return "[non-text]" },
})
},
ToolCall: func(v acp.SessionUpdateToolCall) string {
return v.Title
},
Default: func() string { return "" },
})
Matchers are available for all union types: SessionUpdate, ContentBlock, ToolCallContent, RequestPermissionOutcome, MCPServer.
Connection Options
acp.NewConnection(handler, reader, writer,
acp.WithWriteQueueSize(500), // configurable write queue
acp.WithRequestTimeout(30 * time.Second), // default request timeout
acp.WithShutdownTimeout(10 * time.Second), // graceful shutdown timeout
acp.WithErrorHandler(func(err error) { ... }), // error callback
)
Protocol Support
This implementation supports ACP Protocol Version 1 with the following features:
Agent Methods (Client → Agent)
initialize- Initialize the agent and negotiate capabilitiesauthenticate- Authenticate with the agent (optional)session/new- Create a new conversation sessionsession/load- Load an existing session (if supported)session/list- List available sessionssession/set_mode- Change session modesession/set_config_option- Update session configurationsession/prompt- Send user prompt to agentsession/cancel- Cancel ongoing operations
Client Methods (Agent → Client)
session/update- Send session updates (notifications)session/request_permission- Request user permission for operationsfs/read_text_file- Read text file from client filesystemfs/write_text_file- Write text file to client filesystem- Terminal Support (unstable):
terminal/create- Create terminal sessionterminal/output- Get terminal outputterminal/wait_for_exit- Wait for terminal exitterminal/kill- Kill terminal processterminal/release- Release terminal handle
Unstable Features
session/fork- Fork a session (viaSessionForkerinterface)session/resume- Resume a session (viaSessionResumerinterface)session/close- Close a session (viaSessionCloserinterface)session/set_model- Set model (viaModelSetterinterface)
Fork Maintenance
This repository is a hard fork of github.com/ironpark/go-acp. The module path was renamed to git.goclaw.org/roelfdiedericks/acp-go for Forgejo-hosted maintenance.
To pull future changes from the GitHub upstream after the upstream remote has been wired locally:
git fetch upstream
git merge upstream/master
goimports -w -r 'github.com/ironpark/go-acp -> git.goclaw.org/roelfdiedericks/acp-go' .
Then review the rewritten imports, rerun go mod tidy, go build ./..., and go test ./..., then commit and push the fork updates.
Contributing
This is an unofficial implementation. For protocol specification changes, please contribute to the official repository.
For Go implementation issues and improvements, please open an issue or pull request.
License
This implementation follows the same license as the official ACP specification.
Related Projects
- Official ACP Repository: zed-industries/agent-client-protocol
- Rust Implementation: Part of the official repository
- Protocol Documentation: agentclientprotocol.com
Editors with ACP Support
- Zed
- neovim through the CodeCompanion plugin
- yetone/avante.nvim: A Neovim plugin designed to emulate the behaviour of the Cursor AI IDE
