Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
68a4507
Add user orchestrator agent messaging and observe
sethkarten Jun 18, 2026
08aa1f1
Add orchestration heartbeat skill
sethkarten Jun 18, 2026
44d137a
Address user orchestrator PR review comments
sethkarten Jun 18, 2026
da7d873
Tighten agent message rate limiting
sethkarten Jun 18, 2026
9cff30b
Harden agent message queue safety
sethkarten Jun 18, 2026
bb78549
Preserve agent message reservations on queue clear
sethkarten Jun 18, 2026
1706020
Serialize agent messages per target
sethkarten Jun 18, 2026
16b1c76
Handle queued agent message edge cases
sethkarten Jun 18, 2026
f4d471c
Preserve orchestration heartbeat schedule on refresh
sethkarten Jun 18, 2026
1ba6cd7
Merge main into user orchestrator
sethkarten Jun 29, 2026
c5aa8e6
Merge remote-tracking branch 'origin/main' into feature/user-orchestr…
sethkarten Jun 29, 2026
eae5588
Fix agent message queue handling
sethkarten Jun 29, 2026
d29f863
Fix agent message review issues
sethkarten Jun 30, 2026
180e727
Defer agent message acknowledgment past stream start
sethkarten Jun 30, 2026
b14752f
Fix agent message acceptance race
sethkarten Jun 30, 2026
96ec881
Avoid blocking agent message send on pre-prompt work
sethkarten Jun 30, 2026
d942a14
Avoid blocking agent messages on pre-prompt hooks
sethkarten Jun 30, 2026
6e7f71d
Hide daemon prompt fast path from public options
sethkarten Jun 30, 2026
45dec5f
fix(coding-agent): harden agent message delivery
sethkarten Jun 30, 2026
102bd3f
fix(coding-agent): keep failed agent messages from consuming limits
sethkarten Jun 30, 2026
5839208
fix(coding-agent): address agent orchestrator review issues
sethkarten Jun 30, 2026
f126ff3
fix(coding-agent): address agent orchestrator review issues
sethkarten Jun 30, 2026
4519211
merge remote feature/user-orchestrator
sethkarten Jun 30, 2026
e30af89
merge remote feature/user-orchestrator
sethkarten Jun 30, 2026
fd55d2b
fix(coding-agent): queue sends during accepted retries
sethkarten Jun 30, 2026
d7fe172
merge remote feature/user-orchestrator
sethkarten Jun 30, 2026
e6f7040
fix(coding-agent): address remaining orchestrator bot findings
sethkarten Jun 30, 2026
5735cc4
merge main into user orchestrator branch
sethkarten Jun 30, 2026
4189986
test(coding-agent): update streaming prompt guard expectation
sethkarten Jun 30, 2026
dd0442f
test(coding-agent): remove duplicate daemon queue case
sethkarten Jun 30, 2026
c493acd
fix(coding-agent): harden prompt acceptance races
sethkarten Jun 30, 2026
fb077c0
fix(coding-agent): serialize agent message clearing
sethkarten Jun 30, 2026
03dd462
fix(coding-agent): lock agent message safety controls
sethkarten Jun 30, 2026
a54a99e
fix(coding-agent): harden agent message pause
sethkarten Jun 30, 2026
b53f038
fix(coding-agent): queue agent messages internally
sethkarten Jul 1, 2026
56e280a
fix(coding-agent): release prompt lock when streaming starts
sethkarten Jul 1, 2026
b7d81f7
fix(coding-agent): reject messages paused while locked
sethkarten Jul 1, 2026
e11ca91
fix(coding-agent): reject messages after session switch
sethkarten Jul 1, 2026
0006acc
fix(coding-agent): serialize session close with messages
sethkarten Jul 1, 2026
78f1af8
fix(coding-agent): reject messages for closing sessions
sethkarten Jul 1, 2026
502bca3
Merge remote-tracking branch 'origin/main' into feature/user-orchestr…
sethkarten Jul 1, 2026
ea5d0bd
fix(coding-agent): queue messages during compaction
sethkarten Jul 1, 2026
7f9e886
fix(coding-agent): avoid blocking messages during prompt prep
sethkarten Jul 1, 2026
951da7d
fix(coding-agent): track queued agent messages
sethkarten Jul 1, 2026
c7e6d6d
fix(coding-agent): preserve agent message queue identity
sethkarten Jul 1, 2026
7375570
fix(coding-agent): parse canonical agent message ids
sethkarten Jul 1, 2026
e1cb216
fix(coding-agent): clear accepted agent messages
sethkarten Jul 1, 2026
3df464c
fix(coding-agent): sanitize agent message metadata
sethkarten Jul 1, 2026
b89b4fa
fix(coding-agent): suppress cleared accepted messages
sethkarten Jul 1, 2026
c8b583b
fix(coding-agent): clear accepted prompt state on failure
sethkarten Jul 1, 2026
e5ca7fe
fix(coding-agent): account for accepted message delivery
sethkarten Jul 1, 2026
807fa06
fix(coding-agent): close accepted prompt busy gap
sethkarten Jul 1, 2026
43a6648
fix(coding-agent): harden accepted message cleanup
sethkarten Jul 1, 2026
5a409c2
fix(coding-agent): report accepted messages as pending
sethkarten Jul 1, 2026
d10b2cb
fix(coding-agent): wait for accepted message delivery
sethkarten Jul 1, 2026
27638aa
fix(coding-agent): report duplicate follow-up preflight
sethkarten Jul 1, 2026
63746d5
fix(coding-agent): reject cleared accepted messages
sethkarten Jul 1, 2026
4e8e4ee
fix(coding-agent): reject failed agent message delivery
sethkarten Jul 1, 2026
0cb8af8
fix(coding-agent): emit cleared accepted agent end
sethkarten Jul 1, 2026
8a3140f
fix(coding-agent): unblock idle prompts after agent delivery
sethkarten Jul 1, 2026
4c8d2e3
fix(coding-agent): wait for agent message delivery
sethkarten Jul 1, 2026
48468ac
fix(coding-agent): avoid direct delivery waiter hang
sethkarten Jul 1, 2026
f65a8c6
fix(coding-agent): settle late agent message waits
sethkarten Jul 1, 2026
9136eb3
fix(coding-agent): reject delivery waits on dispose
sethkarten Jul 1, 2026
94e8b6f
fix(coding-agent): acknowledge queued agent messages
sethkarten Jul 1, 2026
5c456af
Merge remote-tracking branch 'origin/main' into feature/user-orchestr…
sethkarten Jul 1, 2026
33759eb
fix(coding-agent): review fixes for agent messaging admission, capaci…
kevinjosethomas Jul 1, 2026
aa83217
fix(coding-agent): drain agent messages after bash
sethkarten Jul 1, 2026
cb362b5
fix(coding-agent): preserve queued message order after bash
sethkarten Jul 1, 2026
6023e56
fix(coding-agent): resolve queued agent-message sends without blockin…
kevinjosethomas Jul 1, 2026
f7928ec
Merge remote-tracking branch 'origin/feature/user-orchestrator' into …
kevinjosethomas Jul 1, 2026
3381a91
fix(coding-agent): report busy observed sessions
sethkarten Jul 1, 2026
7d0cdc6
fix(coding-agent): settle agent-message lifecycle edge cases
sethkarten Jul 1, 2026
c28c53d
fix(coding-agent): keep deferred agent messages ordered
sethkarten Jul 1, 2026
5d8535c
fix(coding-agent): harden queued message cleanup
sethkarten Jul 2, 2026
d53e443
fix(coding-agent): report queued direct accepts
sethkarten Jul 2, 2026
cb192f8
fix(coding-agent): harden agent message delivery state
sethkarten Jul 2, 2026
12f3a0d
fix(coding-agent): restore next-turn context after failed accept
sethkarten Jul 2, 2026
d53aef0
fix(coding-agent): defer cron while agent accepts messages
sethkarten Jul 2, 2026
0575e9e
fix(coding-agent): queue cron during agent-message accept
sethkarten Jul 2, 2026
52719ef
fix(coding-agent): normalize orchestration heartbeat intervals
sethkarten Jul 2, 2026
009ef1c
Merge remote-tracking branch 'origin/main' into feature/user-orchestr…
sethkarten Jul 2, 2026
7ca681b
fix(coding-agent): recheck busy state before direct accept
sethkarten Jul 2, 2026
7bed563
fix(coding-agent): preserve next-turn context in queued accepts
sethkarten Jul 2, 2026
c6c4ad9
fix(coding-agent): settle queued accept edge cases
sethkarten Jul 2, 2026
9454cba
fix(coding-agent): serialize daemon prompts with agent messages
sethkarten Jul 2, 2026
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: 2 additions & 0 deletions packages/coding-agent/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased]

- Added daemon-backed user orchestration with agent-to-agent messaging and read-only observation of active sessions.
- Added an orchestration heartbeat skill for compact multi-session progress, blocker, and action summaries.
- Added an opt-in auto-refine review hook that can ask whether `/refine` should run after turn intervals or compaction checkpoints.

## [0.2.4] - 2026-07-01
Expand Down
38 changes: 38 additions & 0 deletions packages/coding-agent/skills/agent-message/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
name: agent-message
description: Message other active Prime Agent sessions through the daemon. Use to discover active agents and send a direct text message without spoofing sender identity.
---

# Agent Message

Send direct messages to other active Prime Agent sessions through the local
daemon. The daemon derives your sender identity from the current session; do
not try to include a `from` field.

Call directly from the kernel:

```python
agents = await agent_message.list_agents()
receipt = await agent_message.send("worker", "Please inspect the latest result.", mode="auto")
```

## API

- `await agent_message.list_agents()` — returns `current` and `agents`, where
each agent includes active session id, session id, optional name, runtime
kind, cwd, streaming state, and pending message count.
- `await agent_message.send(target, message, mode="auto")` — sends one direct
text message to an active session. `target` is resolved by the daemon like
other live-session selectors. `mode` is `"auto"`, `"follow_up"`, or
`"steer"`. Returns a receipt with a `deliveryStatus` field: `"delivered"`
means the message reached an idle target's context; `"queued"` means it was
accepted and will deliver when the target's current work allows (`send`
does not block waiting for that). Delivered receipts carry `deliveredAt`,
queued receipts carry `queuedAt`.

## Safety

- Broadcast sends are not supported.
- Sender identity is daemon-derived and cannot be spoofed from Python.
- The daemon enforces message size, rate, and pending-queue limits before
accepting delivery.
13 changes: 13 additions & 0 deletions packages/coding-agent/skills/agent-message/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[project]
name = "agent-message"
version = "0.1.0"
description = "Prime Agent session-to-session messaging skill"
requires-python = ">=3.10"
dependencies = []

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/agent_message"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""Prime Agent session-to-session messaging skill.

All routing and sender identity live in the TypeScript daemon. These functions
only call the host bridge exposed inside the Prime Agent IPython kernel.
"""

from __future__ import annotations

from typing import Any, Literal

from rlm import host_request

MessageMode = Literal["auto", "follow_up", "steer"]


async def list_agents() -> dict[str, Any]:
"""List active daemon sessions addressable by agent_message.send()."""
return await host_request("agent_message.list")


async def send(target: str, message: str, mode: MessageMode = "auto") -> dict[str, Any]:
"""Send one direct text message to another active Prime Agent session.

Args:
target: Active session id, session id/name, or unambiguous suffix.
message: Text payload to deliver.
mode: "auto" queues as follow-up only if the target is streaming;
"follow_up" always uses follow-up when the target is streaming;
"steer" interrupts a streaming target.

Returns a receipt dict whose "deliveryStatus" is "delivered" (reached an
idle target's context) or "queued" (accepted; delivers when the target's
current work allows -- this call does not block waiting for that).
"""
if not isinstance(target, str):
raise TypeError(f"target must be str, got {type(target).__name__}")
if not isinstance(message, str):
raise TypeError(f"message must be str, got {type(message).__name__}")
if mode not in ("auto", "follow_up", "steer"):
raise ValueError('mode must be "auto", "follow_up", or "steer"')
return await host_request(
"agent_message.send",
{
"target": target,
"message": message,
"mode": mode,
},
)
39 changes: 39 additions & 0 deletions packages/coding-agent/skills/agent-observe/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
name: agent-observe
description: Read-only observation of active Prime Agent sessions through the local daemon. Use to list agents, inspect session status, and read bounded recent-message previews without mutating other sessions.
---

# Agent Observe

Observe active Prime Agent sessions through the local daemon. This skill is
read-only: it can list sessions, inspect one session, and fetch bounded recent
message previews. It cannot prompt, steer, clear, kill, rename, or otherwise
mutate another session.

Call directly from the kernel:

```python
agents = await agent_observe.list_agents()
worker = await agent_observe.get_agent("worker")
recent = await agent_observe.recent_messages("worker", limit=6)
```

## API

- `await agent_observe.list_agents()` returns `current` and `agents`. Each
agent includes active session id, session id, optional name, runtime kind,
cwd, status, streaming state, message count, pending count, and a latest
message preview.
- `await agent_observe.get_agent(target)` returns one agent summary. `target`
is resolved like other live-session selectors: active id, session id/name, or
unambiguous suffix.
- `await agent_observe.recent_messages(target, limit=8, max_chars=800)`
returns up to `limit` recent bounded message previews for the target session.
`limit` must be 1-50, and `max_chars` must be 80-2000.

## Safety

- This skill is read-only and exposes no mutation commands.
- Message access is bounded by count and per-message character limit.
- Prefer status and recent previews for orchestration. Ask the user before
using observed context to steer or message another session.
15 changes: 15 additions & 0 deletions packages/coding-agent/skills/agent-observe/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[project]
name = "agent-observe"
version = "0.1.0"
description = "Read-only Prime Agent session observation skill"
requires-python = ">=3.10"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/agent_observe"]

[tool.prime_agent.skill]
import = "agent_observe"
Comment thread
macroscopeapp[bot] marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Read-only Prime Agent session observation skill.

All session lookup and data access live in the TypeScript daemon. These
functions only call the host bridge exposed inside the Prime Agent IPython
kernel.
"""

from __future__ import annotations

from typing import Any

from rlm import host_request


async def list_agents() -> dict[str, Any]:
"""List active daemon sessions visible to this agent."""
return await host_request("agent_observe.list")


async def get_agent(target: str) -> dict[str, Any]:
"""Read one active session summary by active id, session id/name, or suffix."""
if not isinstance(target, str):
raise TypeError(f"target must be str, got {type(target).__name__}")
return await host_request("agent_observe.get", {"target": target})


async def recent_messages(
target: str,
limit: int = 8,
max_chars: int = 800,
) -> dict[str, Any]:
"""Read bounded recent message previews from an active session.

Args:
target: Active session id, session id/name, or unambiguous suffix.
limit: Number of recent messages to return. Host validates 1-50.
max_chars: Per-message preview size. Host validates 80-2000.
"""
if not isinstance(target, str):
raise TypeError(f"target must be str, got {type(target).__name__}")
if not isinstance(limit, int):
raise TypeError(f"limit must be int, got {type(limit).__name__}")
if not isinstance(max_chars, int):
raise TypeError(f"max_chars must be int, got {type(max_chars).__name__}")
return await host_request(
"agent_observe.recent",
{
"target": target,
"limit": limit,
"max_chars": max_chars,
},
)
41 changes: 41 additions & 0 deletions packages/coding-agent/skills/orchestration-heartbeat/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
name: orchestration-heartbeat
description: Initialize or refresh an internal orchestrator heartbeat that observes active Prime Agent sessions, summarizes progress and blockers, and recommends next actions or messages.
---

# Orchestration Heartbeat

Use this skill from an orchestrator session to create or refresh a recurring
internal heartbeat for supervising multiple active Prime Agent sessions.

The heartbeat is an RLM heartbeat, not the user's visible `/heartbeat`. It
cannot read, replace, pause, resume, or clear the user-level heartbeat.

Call directly from IPython:

```python
await orchestration_heartbeat.initialize()
await orchestration_heartbeat.initialize(interval="10m", focus="EmulatorBench and AutoEnv")
```

## API

- `await orchestration_heartbeat.initialize(interval="5m", label="orchestrator",
focus=None, require_user_approval=True)` creates or updates the labeled
orchestrator heartbeat for the current session.
- `await orchestration_heartbeat.ensure(...)` is an alias for `initialize`.
- `orchestration_heartbeat.build_instruction(...)` returns the prompt text
without creating or updating a heartbeat.

## Heartbeat Behavior

Each recurring orchestration heartbeat should:

- Inspect active sessions with `agent_observe`.
- Summarize each relevant session as `active`, `waiting`, `blocked`, `error`,
or `completed`.
- Include current progress and explicit blockers.
- Recommend the next action and, when useful, draft a target message.
- Ask for user approval before sending cross-session messages unless the user
has already approved that specific messaging policy.
- Keep the update compact and operational instead of dumping logs.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[project]
name = "orchestration-heartbeat"
version = "0.1.0"
description = "Prime Agent orchestration heartbeat skill"
requires-python = ">=3.10"
dependencies = ["agent-observe", "rlm-heartbeat"]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/orchestration_heartbeat"]
Loading