Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion IMPLEMENTATION_STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ compatibility, security, and release contracts recorded in the repository.

The local four-agent deployment uses AgentPost as its sole actionable
development-agent channel. The 1.3.0 release packages Claude plugin generation
0.0.7, Codex plugin generation `0.0.6+codex.20260728214546`, and Python package
0.0.8, Codex plugin generation `0.0.7+codex.20260804015728`, and Python package
version 1.3.0.
Plugin generations identify independently deployed adapter artifacts and do
not replace the Python package's semantic version.
Expand Down
56 changes: 42 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ Other Examples:
- Replying atomically claims an exact unread original; already-read originals
remain replyable for corrections.
- Notifications are pointers. The mailbox is always the durable truth.
- Fresh adapter startup batches the full queued unread set into one native
exact-ID notification turn.
- Fresh interactive-adapter startup batches the full queued unread set into one
consent gate. The agent reports the mailbox and count, then asks whether to
inspect that exact set now, reload or rebind first, or defer it. Startup
priority never authorizes reading or claiming mail.
- A mailbox belongs to a durable agent identity, not to one CLI process.
- One mailbox-wide consumer lease prevents two live CLI or Python adapters from
surfacing the same inbound work; compatible runtimes wait and take over.
Expand Down Expand Up @@ -125,10 +127,12 @@ and specialist queues.

Antigravity CLI 1.1.1 has a validated lifecycle catch-up profile. Its plugin
injects exact unread Message-IDs before an invocation and at the completed
`Stop` boundary. Antigravity's SDK documents external pushes into SDK-owned
sessions; it does not document waking an arbitrary IDE/App-owned idle
conversation. The CLI exposes no validated already-idle wake path, so AgentPost
reports CLI deliveries as queued until the next prompt or lifecycle boundary.
`Stop` boundary. Its first host-process snapshot is a consent gate; later mail
uses the ordinary exact-ID instruction. Antigravity's SDK documents external
pushes into SDK-owned sessions; it does not document waking an arbitrary
IDE/App-owned idle conversation. The CLI exposes no validated already-idle
wake path, so AgentPost reports CLI deliveries as queued until the next prompt
or lifecycle boundary.
Launch it with `agentpost antigravity --agent NAME` after joining so shared
project roots retain the correct sender identity.

Expand Down Expand Up @@ -264,6 +268,26 @@ defaults for hooks and AgentPost CLI subprocesses, but explicit `--from`,
`--agent`, and `AGENTPOST_AGENT` still outrank it. See
[Codex session attach](specs/CODEX-SESSION-ATTACH-V1.md).

Managed consumers report held leases independently from heartbeat presence. A
suspended terminal job therefore appears as `suspended`, not misleadingly
offline. If the user intended to close that exact managed instance, AgentPost
prints a guarded recovery command shaped as:

```sh
agentpost consumer-stop reviewer --instance FULL_INSTANCE_ID
```

The full instance guard prevents a stale instruction from stopping a
replacement consumer. It releases the process tree and lease without deleting
mail, identity state, bindings, or attachments. Managed Codex and Antigravity
sessions convert terminal suspension into clean shutdown because a stopped
bridge cannot provide wake while retaining exclusive mailbox ownership.

Managed Codex owner metadata also records a digest of a resumed thread ID. A
resume under another AgentPost seat fails before startup when that thread is
already managed elsewhere and prints the existing seat and exact recovery
command. See [safe session re-entry](specs/SAFE-SESSION-REENTRY-V1.md).

If an existing unread letter needs another native notification, its original
sender can re-fire attention without resending content:

Expand Down Expand Up @@ -419,9 +443,11 @@ idle.
native monitor event only when unread mail appears. Lifecycle hooks maintain
a short busy/idle boundary in the mailbox's AgentPost adapter directory. A
fresh Claude load starts the monitor automatically; no model call is made
until mail causes a native event. The event names the optional
`/agentpost:agentpost` skill and includes exact positional `read` and `next`
commands, so inspection remains retry-safe when the skill is unavailable.
until mail causes a native event. Its initial event announces only the queued
count and asks whether to inspect, reload, or defer. Later live events name
the optional `/agentpost:agentpost` skill and include exact positional `read`
and `next` commands, so inspection remains retry-safe when the skill is
unavailable.
- `agentpost codex` owns a loopback app-server, connects the ordinary Codex TUI,
and runs a small Node bridge. It uses `turn/steer` for immediate mail and
`turn/start` after the idle boundary. For ordinary Codex launches, plugin
Expand Down Expand Up @@ -513,11 +539,13 @@ load; managed Codex must attach its app-server bridge; ordinary Codex proves
lifecycle-hook catch-up only; Antigravity proves hook injection at its first
`PreInvocation`; and Python delegates turn creation to its host scheduler.

Every native exact-ID pointer is self-sufficient when its optional skill is not
available. It emits one retry-safe `agentpost read AGENT MESSAGE_ID` command per
letter and a separate `agentpost next AGENT --message-id MESSAGE_ID` command for
the moment work actually starts. Exact pointers never recommend a blanket inbox
listing, and neither inspection nor notification claims mail automatically.
Every post-startup native exact-ID pointer is self-sufficient when its optional
skill is not available. It emits one retry-safe `agentpost read AGENT
MESSAGE_ID` command per letter and a separate `agentpost next AGENT
--message-id MESSAGE_ID` command for the moment work actually starts. Startup
gates intentionally omit those commands until the user consents. Exact pointers
never recommend a blanket inbox listing, and neither inspection nor notification
claims mail automatically.

## Documentation

Expand Down
2 changes: 2 additions & 0 deletions docs/COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ documented migration and deprecation path.
success must not be reported as live wake or presence.
- Public Python names exported through `agentpost.__all__`, including
`PostOffice`, `AgentChannel`, and `AgentRuntime`.
- `Notification.origin` is additive routing metadata. Existing positional
construction remains valid because it defaults to `live`.
- `PROJECT.SEAT` remains the explicit cross-project human address. Sender-bound
bare identity resolution must stay inside shared registered project entries
and must never fall back to another project's globally unique seat. Dot
Expand Down
42 changes: 30 additions & 12 deletions docs/INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,8 +375,11 @@ denied while `send-path` passes, the denial is in the host CLI's permission
configuration, not in AgentPost.

On managed startup, all queued unread Message-IDs are named together in the
first native notification turn. To re-fire attention for one existing unread
letter without duplicating it, its sender runs:
first native notification turn, but that turn is a consent gate: it reports the
mailbox and count and asks whether to inspect now, reload or rebind first, or
defer. It does not include inspection or claim commands before the user chooses.
To re-fire attention for one existing unread letter without duplicating it, its
sender runs:

```sh
agentpost notify RECIPIENT MESSAGE_ID --mode immediate
Expand Down Expand Up @@ -444,8 +447,9 @@ agentpost antigravity --agent app
Restart through the AgentPost launcher after first installation. It sets the
per-process mailbox identity, which matters when multiple CLI agents share one
project root. The plugin uses `PreInvocation` and `Stop` hooks to inject exact
unread Message-IDs without claiming them. It supports startup/next-prompt
catch-up and completed-turn idle delivery.
unread Message-IDs without claiming them. The first host-process snapshot is a
consent gate; later mail uses the ordinary exact-ID workflow. It supports
startup/next-prompt catch-up and completed-turn idle delivery.

Antigravity's SDK documents external pushes into SDK-owned sessions. Current
official material does not document waking an arbitrary IDE/App-owned idle
Expand All @@ -454,27 +458,41 @@ conversation, and live CLI 1.1.1 acceptance exposed no already-idle wake path.
conservatively see delivery as queued. Do not compensate with terminal
keystroke injection or a duplicate message channel.

Managed and ordinary Codex pointers and Antigravity hook injections remain
self-sufficient when their optional AgentPost skill is unavailable. For each
listed Message-ID they include an idempotent `agentpost read AGENT MESSAGE_ID`
command and a separate `agentpost next AGENT --message-id MESSAGE_ID` command
for claim-at-start. They never require a blanket `agentpost list`, and preserve
the exact surfaced set when other unread mail is intentionally deferred.
Post-startup managed and ordinary Codex pointers and Antigravity hook injections
remain self-sufficient when their optional AgentPost skill is unavailable. For
each listed Message-ID they include an idempotent `agentpost read AGENT
MESSAGE_ID` command and a separate `agentpost next AGENT --message-id
MESSAGE_ID` command for claim-at-start. Startup gates intentionally omit those
commands until the user consents. Neither form requires a blanket `agentpost
list`, and both preserve the exact surfaced set when other unread mail is
intentionally deferred.

## Recovery

Mail delivery does not depend on an adapter being healthy. If a native bell
fails, restart the CLI integration and inspect the complete unread set:
fails, restart the CLI integration; its startup gate will report the queued
count and wait for the user's choice. After explicit approval to inspect, these
commands diagnose or recover the exact mailbox:

```sh
agentpost list AGENT
agentpost read AGENT GATED_MESSAGE_ID
agentpost armed AGENT
agentpost status AGENT
agentpost profiles --offline
agentpost doctor AGENT --project /work/project --cli claude
agentpost doctor AGENT --project /work/project --cli codex
```

If status reports a suspended managed owner that the user intended to close,
run only the exact instance-guarded command printed by AgentPost:

```sh
agentpost consumer-stop AGENT --instance FULL_INSTANCE_ID
```

Then retry the original named launcher. This recovery does not delete or move
mail and is not a reason to create a numbered mailbox.

For incomplete Codex trust, approve the stable AgentPost hooks in `/hooks`. For
a stale installed cache, close all Codex sessions and re-run `agentpost install
codex --confirm-codex-sessions-closed` (or the same `join` command with that
Expand Down
12 changes: 12 additions & 0 deletions docs/PROTOCOL.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,15 @@ counts; later responses remain visible as duplicates.
Notification adapters receive only committed Message-IDs. Adapter failure does
not roll back delivery, and adapter state is never authoritative for unread
state. Adapter activation always catches up from the full current unread set.
Interactive adapters surface that startup snapshot as a consent gate: they
announce the mailbox and exact pending set but prohibit inspection, claim,
reply, or work until the user chooses to read now, reload or rebind first, or
defer. An attention-request record may be acknowledged when the gate is
delivered; the durable message remains unread and is gated again after a
runtime reload.

Consumer ownership and heartbeat presence are independent evidence. A fresh
matching heartbeat plus a held lease is live; a stopped owner holding the lease
is `suspended`; a running owner with a stale heartbeat is `unresponsive`.
Neither recovery state is treated as an offline/free mailbox or as a reason to
create a parallel numbered identity.
8 changes: 8 additions & 0 deletions docs/PYTHON.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,14 @@ A notification contains only routing data and the immutable spool path:
- `kind`
- `notify`
- `path`
- `origin`: `startup`, `live`, or `snapshot`

The first batch after a runtime acquires the mailbox lease uses
`origin="startup"`. Interactive hosts should present that batch as a user
consent gate rather than enqueue model work immediately. `AgentRuntime` remains
transport-only: it does not ask the user, call a model, inspect content, or
claim mail. Later batches use `origin="live"`; side-effect-free reconciliation
through `runtime.unread()` uses `origin="snapshot"`.

The application may inspect with `PostOffice.read()` and must call
`PostOffice.claim()` only when it actually starts the work. This preserves the
Expand Down
18 changes: 12 additions & 6 deletions docs/TWO_AGENT_QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ agentpost doctor agent-one --project "$PWD" --cli claude

Restart or reload the Claude project session after `join`. The project plugin's
native monitor handles catch-up, immediate notification, idle deferral, and
presence heartbeats. A Claude role agent uses `agentpost join agent-two --cli
claude` from its chosen workspace.
presence heartbeats. If queued mail exists on that fresh load, the monitor asks
whether to inspect it now, reload or rebind first, or defer it. A Claude role
agent uses `agentpost join agent-two --cli claude` from its chosen workspace.

### Codex

Expand All @@ -135,7 +136,8 @@ Codex process that predates the prompt hook, then submit and complete one prompt
so `doctor` can verify the active generation. Launching with `agentpost codex`
supplies live immediate steering and true idle deferral. An ordinary Codex
launch checks at startup, before each prompt, and at turn completion but does
not provide already-idle wake.
not provide already-idle wake. Both paths gate queued startup mail before any
inspection command is offered.

### Embedded Python

Expand Down Expand Up @@ -167,8 +169,9 @@ agentpost antigravity --agent agent-two
```

Restart `agy` after the first `join`. Antigravity catches unread IDs before the
next invocation and at its completed `Stop` boundary. Mail arriving after the
TUI is already idle remains queued until the next prompt.
next invocation and at its completed `Stop` boundary. Its first snapshot asks
whether to inspect, reload or rebind, or defer; mail arriving after the TUI is
already idle remains queued until the next prompt.

## 5. Tell them to talk

Expand Down Expand Up @@ -212,11 +215,13 @@ print(result.message_id)

The native monitor wakes the project session with the exact Message-ID. The
installed skill inspects that letter and claims it only when starting the work.
On fresh startup, it asks for consent before that inspection workflow.

### Codex

The app-server bridge starts or steers the turn with the exact Message-ID. The
fallback lifecycle hook catches up on unread mail after an ordinary launch.
Queued startup mail is announced through the same consent gate before reading.

### Embedded Python

Expand All @@ -228,7 +233,8 @@ admitted.

The plugin injects the exact Message-ID at the next invocation or completed
turn boundary. It never claims mail. Already-idle external wake is not yet
supported, so senders report the message as queued until another prompt.
supported, so senders report the message as queued until another prompt. A
fresh host process gates its initial unread snapshot before inspection.

### Portable CLI workflow

Expand Down
35 changes: 30 additions & 5 deletions integrations/antigravity/skills/agentpost/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,16 @@ If a connection attempt reports that `NAME` already has an inbound consumer,
do not steal its lease or silently treat mailbox-level `ARMED` as proof that
this process connected. Report the existing owner. If it is this managed
session's parent bridge, continue in the existing session. Otherwise inspect
the exact identities and offer the user the first unused numbered mailbox,
starting with `NAME2`, then `NAME3`. Create it only after explicit user approval,
then use the explicit named join and launcher and verify it independently. The
numbered identity is a separate durable mailbox: it does not inherit, claim, or
move mail already addressed to `NAME`.
the exact identities and owner state. A suspended or unresponsive managed
consumer is a recovery condition, not parallel work: do not offer a numbered
mailbox. If the user confirms that exact instance was intended to close, use
the native `agentpost consumer-stop NAME --instance FULL_INSTANCE_ID` command
printed by AgentPost, then retry the original launcher. For a healthy unrelated
owner and genuinely parallel work, offer the user the first unused numbered
mailbox, starting with `NAME2`, then `NAME3`. Create it only after explicit user
approval, then use the explicit named join and launcher and verify it
independently. The numbered identity is a separate durable mailbox: it does not
inherit, claim, or move mail already addressed to `NAME`.

Do not rewrite integration state ad hoc or launch a nested copy of the current
CLI. An ordinary running Codex thread with compatible AgentPost hooks may select
Expand Down Expand Up @@ -201,6 +206,26 @@ Familiarity does not outrank a better responsibility or evidence match.

## Mail workflow

### Startup consent gate

When a native notification begins with `AgentPost startup notice`, it is an
attention gate, not authorization to process mail. Do not run `agentpost list`,
`read`, `next`, or `reply`, and do not begin any workflow described by the
pending mail. Tell the user only the pending count and selected mailbox, then
ask whether to inspect that exact set in the current session, reload or rebind
the intended session first, or defer it.

- If the user chooses **read now**, inspect exactly the Message-IDs embedded in
that startup notice, then use the normal claim and reply workflow below.
- If the user chooses **reload or rebind**, leave every message untouched and
give the exact applicable launcher or attachment command. The replacement
runtime will gate the still-unread set again.
- If the user chooses **defer**, leave every message untouched for this runtime.

Never infer startup consent from `immediate` priority, a prior conversation, a
request to connect the mailbox, or the fact that the native adapter started a
turn. Mail delivered after startup uses the ordinary exact-ID workflow below.

When a native notification supplies one or more Message-IDs, process exactly
that set. Do not run a blanket inbox listing or inspect, claim, or process other
unread letters in that turn; another attention mode may be intentionally
Expand Down
4 changes: 2 additions & 2 deletions integrations/claude/.claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
},
"metadata": {
"description": "Local AgentPost development marketplace",
"version": "0.0.7"
"version": "0.0.8"
},
"plugins": [
{
"name": "agentpost",
"description": "A named local communication channel for CLI agents",
"version": "0.0.7",
"version": "0.0.8",
"author": {
"name": "AgentPost contributors"
},
Expand Down
2 changes: 1 addition & 1 deletion integrations/claude/agentpost/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "agentpost",
"displayName": "AgentPost",
"version": "0.0.7",
"version": "0.0.8",
"description": "A named local communication channel for CLI agents",
"author": {
"name": "AgentPost contributors"
Expand Down
Loading
Loading