acp
A Go client for the Agent Client Protocol, versions 1 and 2. Start a coding agent, open a session, send prompts and read typed updates.
tuios.dev/acp is a Go client for the Agent Client Protocol (ACP). An editor or a terminal uses the protocol to drive a coding agent: it starts the agent, opens a session, sends prompts and reads what the agent does as typed updates. The messages are JSON-RPC 2.0, one per line, on the agent's stdin and stdout. tuios uses this package for its protocol panes (tuios start-agent --protocol acp).
go get tuios.dev/acpThe package uses only the standard library and needs Go 1.25 or later. The API reference is on pkg.go.dev.
What is in it
- The JSON-RPC peer.
Connsends and receives requests in both directions, and handles$/cancel_request. - Version negotiation.
Connectasks for a version. An agent asked for version 2 may answer 1. An agent that refuses 2 is started again through the transport and asked for 1. When no version fits, the error names the versions of both sides. - Sessions. New, resume, list, prompt, cancel and close.
- Updates. Every
session/updatekind is a Go type, in one model for both versions. An unknown kind arrives as*UnknownUpdatewith its raw JSON. - Permission requests. Answer with
ChooseorCancel. The agent can withdraw a request with$/cancel_request. - Transports.
Processstarts the agent and talks over stdio.Pipeworks over a pair of streams.
Run one prompt
package main
import (
"context"
"fmt"
"log"
"os"
"tuios.dev/acp"
)
func main() {
ctx := context.Background()
agent := &acp.Process{Path: "opencode", Args: []string{"acp"}, Stderr: os.Stderr}
c, err := acp.Connect(ctx, agent, acp.ClientOptions{
Info: acp.Implementation{Name: "example", Version: "0.1.0"},
OnUpdate: func(u acp.Update) {
if m, ok := u.(*acp.MessageUpdate); ok && m.Role == acp.RoleAgent && m.Op == acp.MessageAppend {
fmt.Print(m.Text())
}
},
// Dismiss every permission request: the agent does nothing it
// has to ask for.
OnPermission: func(p *acp.PermissionRequest) { p.Cancel() },
})
if err != nil {
log.Fatal(err)
}
defer c.Close()
cwd, _ := os.Getwd()
s, err := c.NewSession(ctx, cwd)
if err != nil {
log.Fatal(err)
}
end, err := s.Prompt(ctx, acp.Text("Summarise the TODO comments in this folder."))
if err != nil {
log.Fatal(err)
}
fmt.Println("\nstopped:", end.Reason)
}OnUpdate and OnPermission run on the read goroutine of the connection, in the order the agent sent the messages. They must not block. Answer a permission request from any goroutine.
The package passes the text of the agent through as it came. The text can hold terminal escape sequences. A program that draws it in a terminal must remove them first.
Versions of the protocol
| Version | Status in the spec | In this package |
|---|---|---|
| 1 | stable | spoken, the default |
| 2 | draft | spoken when ClientOptions.MaxVersion is 2 |
The spec asks clients not to ask for version 2 by default while it is a draft, so DefaultVersion is 1 and LatestVersion is 2. Set MaxVersion: 2 in the options to ask for version 2 first. The version 2 schema can still change. This package follows the draft of 2026-11-13.
Updates follow the version 2 model, which can say more. A version 1 update arrives as the same type, with the fields that version 1 cannot state left at their zero value. In version 2 the answer to a prompt only says that the agent took the prompt. Session.Prompt waits for the state_update to idle that ends the turn, so it returns at the end of the turn in both versions.
The client offers the agent no file system and no terminal, so a conforming agent does its own reads, writes and commands. The agent side of the protocol is not in the package.
API overview
| Name | Does |
|---|---|
Connect, ClientOptions | Start a connection and negotiate the version. |
Process, Pipe | The transports. |
Conn | The JSON-RPC peer. |
Session | New, resume, list, prompt, cancel and close. |
Update, UnknownUpdate | What the agent reports during a turn. |
PermissionRequest | A question from the agent, answered with Choose or Cancel. |
What stays in tuios
tuios keeps the pane program (agent-proto) and its transcript, the agent state and the Inbox reports, the keys that answer a permission, and the [agents] acp_version option. tuios does not use acp.Process. A protocol pane starts its agent through its own transport, so the agent gets no controlling terminal.
Versions
The module is at v0 and has no tag yet. The API can change between minor versions. Its tags will have the folder name as a prefix, such as acp/v0.1.0. The source is in the acp folder of the tuios repository, under the MIT licence.
sketch playground
Type Mermaid and see sketch draw it as you type. sketch runs in your browser as WebAssembly.
harness
Recognise coding-agent CLIs and read their state from the screen. One TOML manifest per agent, and a reason for every answer.
tuios lives only at tuios.dev and github.com/Gaurav-Gosain/tuios. tuios has no X or Twitter account. An account that offers a tuios token or presale is not this project.