<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[paseo-agy-acp]]></title><description><![CDATA[paseo-agy-acp]]></description><link>https://paseo-agy-acp.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>paseo-agy-acp</title><link>https://paseo-agy-acp.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 31 Aug 2026 00:34:05 GMT</lastBuildDate><atom:link href="https://paseo-agy-acp.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Beyond JSON-RPC: six contracts a production ACP adapter needs]]></title><description><![CDATA[A generic ACP client can initialize a server, open a session, send a prompt, and stream updates. That proves protocol compatibility. It does not make a provider reliable under a real multi-agent contr]]></description><link>https://paseo-agy-acp.hashnode.dev/beyond-json-rpc-six-contracts-a-production-acp-adapter-needs</link><guid isPermaLink="true">https://paseo-agy-acp.hashnode.dev/beyond-json-rpc-six-contracts-a-production-acp-adapter-needs</guid><category><![CDATA[AI]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[Lloyd Ye]]></dc:creator><pubDate>Sun, 30 Aug 2026 04:35:34 GMT</pubDate><content:encoded><![CDATA[<p>A generic ACP client can initialize a server, open a session, send a prompt, and stream updates. That proves protocol compatibility. It does not make a provider reliable under a real multi-agent controller.</p>
<p>I maintain <a href="https://github.com/tiezbro/paseo-agy-acp">paseo-agy-acp</a>, an Apache-2.0 product adapter between Paseo and Google's official Antigravity ACP kernel. Version 2.3.0 is now on npm and can be launched with npx.</p>
<blockquote>
<p>Maintainer disclosure: this is a community project, not official Paseo or Google support. This post was drafted by an AI agent from the project's v2.3.0 documentation on behalf of the maintainer.</p>
</blockquote>
<p>The adapter does not reimplement Antigravity. Google's local kernel remains responsible for OAuth, model discovery, inference, streaming, tools, MCP execution, quotas, and provider errors. The npm package installs only the open-source proxy; it neither contains nor downloads Google's proprietary kernel.</p>
<p>The useful engineering question is narrower: <strong>what contracts are still missing after two products agree on ACP?</strong></p>
<h2>Contract 1: ownership must stay explicit</h2>
<p>The execution chain is intentionally small:</p>
<pre><code class="language-text">Paseo / Generic ACP client
  -&gt; paseo-agy-acp
       context | mode map | MCP rewrite | skill hints
       blank-turn guard | optional Admission fence
  -&gt; official agy_acp_server
       OAuth | models | tools | MCP | inference
</code></pre>
<p>Paseo owns agent lifecycle, workspaces, and delegation. The adapter owns Paseo-specific normalization. The official kernel owns the provider. If a model is unavailable, quota is exhausted, or a tool behaves differently, the adapter surfaces that result instead of pretending it can repair the backend.</p>
<p>That boundary also defines distribution: the adapter is Apache-2.0, while the official kernel remains a separate local proprietary dependency.</p>
<h2>Contract 2: controller context must reach the session</h2>
<p>A session can be protocol-correct and still be operationally wrong.</p>
<p>Paseo launches agents with daemon-side context, a workspace cwd, and agent identity. A raw bridge can successfully forward session/prompt while silently dropping the instructions that tell an agent how to operate in that workspace.</p>
<p>paseo-agy-acp injects the daemon context when PASEO_AGENT_ID is present. The goal is preserving the controller's execution contract across the provider boundary.</p>
<p>This is a recurring integration lesson: transport success says nothing about whether product context survived.</p>
<h2>Contract 3: modes and MCP shapes need deterministic normalization</h2>
<p>Mode identifiers differ between products. The adapter currently maps:</p>
<table>
<thead>
<tr>
<th>Paseo or legacy id</th>
<th>Official live mode</th>
</tr>
</thead>
<tbody><tr>
<td>default</td>
<td>default</td>
</tr>
<tr>
<td>accept-edits</td>
<td>auto_edit</td>
</tr>
<tr>
<td>dangerously-skip-permissions</td>
<td>yolo</td>
</tr>
<tr>
<td>plan</td>
<td>default</td>
</tr>
</tbody></table>
<p>The official live kernel does not expose a plan mode. Mapping it to default is explicit and testable; claiming an unsupported capability would be worse.</p>
<p>MCP configuration has a similar mismatch. Paseo commonly supplies an HTTP-style declaration with headers in a map. The official kernel expects SSE and header entries shaped as name/value pairs. The adapter rewrites that data during session/new so each caller does not need its own Antigravity-specific conversion.</p>
<h2>Contract 4: empty output is an error, not success</h2>
<p>An output-free end_turn is valid protocol data, but it is a poor product result.</p>
<p>Without additional tracking, the controller may store a blank assistant message as a successful turn. That makes failure statistics inaccurate and leaves operators guessing whether the model produced nothing, streaming was lost, or the provider failed internally.</p>
<p>The adapter tracks visible assistant and tool activity. If the official kernel ends the turn with none, it returns an explicit JSON-RPC error. Turning ambiguity into a typed failure improves retry behavior and observability without changing the kernel.</p>
<h2>Contract 5: multi-agent bursts need account-wide Admission</h2>
<p>Paseo can delegate to several agents at once. Each agent may have its own connector process and official-kernel child. If all of them write prompts against one signed-in Antigravity account at the same moment, process-local throttling is insufficient.</p>
<p>paseo-agy-acp places a durable Admission queue immediately before the official session/prompt write. Each turn:</p>
<ol>
<li>joins the account-wide queue,</li>
<li>acquires a seat,</li>
<li>writes the prompt to the official kernel,</li>
<li>releases the seat on completion, failure, or cancellation.</li>
</ol>
<p>Extra turns wait instead of striking the account concurrently.</p>
<p>The tested defaults are <strong>8 active turns, 8 concurrent starts, and 2 seconds minimum start spacing</strong>. These are operating defaults validated under Paseo bursts, not a Google product limit.</p>
<p>Admission state is shared by every connector process using the same owner-only state directory. Invalid policy, missing identity, or permissive filesystem state fails closed when the fence is enabled. Silently switching from fenced to unfenced execution would make incidents difficult to reproduce.</p>
<h2>Contract 6: local commands must remain workspace-scoped</h2>
<p>Version 2.3.0 adds discovery of user-invocable SKILL.md metadata across configured and default Gemini, Agents, Codex, and workspace roots.</p>
<p>The adapter merges those skills into standard ACP slash-command hints while preserving native commands from the official kernel. The precedence rules are:</p>
<ul>
<li>native commands win name collisions,</li>
<li>workspace skills override global skills,</li>
<li>user-invocable: false entries remain hidden,</li>
<li>discovery runs against each session cwd,</li>
<li>concurrent session/new setup is serialized.</li>
</ul>
<p>The cwd boundary matters. Without it, two agents starting in different workspaces could observe each other's command metadata. Version 2.3.0 treats command discovery as session state, not connector-global state.</p>
<p>The release validation covered 37 test files with 216 passing and one skipped. Architecture and secret checks passed. A live official-kernel canary preserved native commands, exposed a visible workspace skill, and kept a non-invocable skill hidden.</p>
<h2>Running v2.3.0 with npx</h2>
<p>Requirements:</p>
<ul>
<li>Paseo with Generic ACP provider support</li>
<li>Node.js 22 or newer</li>
<li>a locally installed official Antigravity ACP kernel wrapper or .par</li>
<li>an Antigravity account able to complete oauth-personal</li>
<li>Linux ownership and mode support when Admission is enabled</li>
</ul>
<p>Authenticate through the official kernel:</p>
<pre><code class="language-bash">export PASEO_AGY_ACP_OFFICIAL_BIN="/absolute/path/to/agy-acp-server-wrapper-or.par"
npx -y paseo-agy-acp@2.3.0 --login
</code></pre>
<p>For multi-agent operation, prepare one state directory per account:</p>
<pre><code class="language-bash">export AGY_ACP_STATE_DIR="$HOME/.local/state/paseo-agy-acp/account-name"
install -d -m 700 "$AGY_ACP_STATE_DIR"

npx -y --package=paseo-agy-acp@2.3.0   agy-acp-prepare-state "$AGY_ACP_STATE_DIR"
</code></pre>
<p>Then point a Paseo provider at the package:</p>
<pre><code class="language-json">{
  "providers": {
    "antigravity": {
      "type": "acp",
      "command": ["npx", "-y", "paseo-agy-acp@2.3.0"],
      "env": {
        "PASEO_AGY_ACP_OFFICIAL_BIN": "/absolute/path/to/agy-acp-server-wrapper-or.par",
        "AGY_ACP_ADMISSION_ENABLED": "true",
        "AGY_ACP_STATE_DIR": "/home/YOU/.local/state/paseo-agy-acp/account-name"
      }
    }
  }
}
</code></pre>
<p>Restart Paseo after changing the provider command or environment. npx starts the stdio adapter consumed by Paseo; it is not a standalone chat application. The official kernel must already be installed and authenticated. The first npm run may compile better-sqlite3 and require a local C++ toolchain.</p>
<h2>What remains provider-owned</h2>
<p>The default official ACP path follows the Gemini-family model set available to the signed-in account. Entitled accounts can use the repository's explicit local compatibility runbook for Claude 4.6 and GPT-OSS 120B, but inference still runs through the same official kernel and Google backend.</p>
<p>That distinction matters when debugging. The adapter can preserve context, normalize requests, pace account access, and make failures visible. It cannot manufacture entitlement or redefine provider capacity.</p>
<h2>The broader lesson</h2>
<p>Protocol adapters become production integrations when their contracts are explicit.</p>
<p>For this project, the critical contracts are ownership, context propagation, deterministic normalization, visible failure semantics, account-wide Admission, and workspace-scoped command discovery. None requires replacing the official provider. Each removes a class of ambiguity at the boundary.</p>
<p>Project: <a href="https://github.com/tiezbro/paseo-agy-acp">github.com/tiezbro/paseo-agy-acp</a></p>
<p>npm: <a href="https://www.npmjs.com/package/paseo-agy-acp">paseo-agy-acp@2.3.0</a></p>
<p>I would especially value reports on Admission settings under real multi-agent bursts and skill isolation across concurrent workspaces.</p>
]]></content:encoded></item></channel></rss>