Automattic / Automattic/agents-api

Convergence audit: merge parallel WordPress agents-api extractions

Open
#77 6 comments 0 reactions 0 assignees View on GitHub
Dominant language
PHP
Stars
33
Forks
8
Avg merge
1h 36m
Merged PRs (30d)
31

Description

## Goal

Two parallel extraction efforts have been building toward an OSS-able WordPress-shaped agents substrate from different starting points:

- This repo (`Automattic/agents-api`), extracted from [`Extra-Chill/data-machine`](https://github.com/Extra-Chill/data-machine).
- A second extraction inside a large WordPress install, extracting from a `lib/ai/agents/` runtime into a local `mu-plugins/agents-api/` package.

The goal is a single OSS plugin that both major adopters (and any future consumer) build on top of, with zero forks. This issue is the convergence map: what overlaps, what diverges, and the PR sequence to land canonical.

## Inventory comparison

### Already in canonical (this repo) but not in the second extraction

The substrate has shipped a much wider contract surface in PRs #65–#73:

- `src/Approvals/` — pending action / approval primitives
- `src/Auth/` — access grants, token store, capability ceiling, authorization policy
- `src/Consent/` — consent policy contracts
- `src/Context/` — composable context, memory layer/registry, authority cascade, conflict resolution
- `src/Identity/` — agent identity scope, materialized identity, store
- `src/Memory/` — full memory store contracts (with workspace + provenance)
- `src/Packages/` — agent package + artifact registry
- `src/Runtime/` — `AgentConversationLoop`, completion policy, transcript persister, compaction, iteration budget, execution principal, message envelope
- `src/Tools/` — tool execution core, source registry, action policy, runtime tool declaration
- `src/Transcripts/` — `ConversationTranscriptStoreInterface`
- `src/Workspace/` — `AgentWorkspaceScope`

### In the second extraction but not in canonical

1. **Heavy `WP_Agent` runtime base class** that integrates LLM loop + provider + session + memory + hooks + context tree + token streaming + async + compaction in one class. Canonical's pattern is the opposite: thin value object (`Registry/class-wp-agent.php`) + `AgentConversationLoop` composition.

2. **Five typed lifecycle event objects** — `WP_Agent_Stream_Delta`, `WP_Agent_Progress`, `WP_Agent_Queued`, `WP_Agent_Input_Required`, `WP_Agent_Final_Result`. These are the working precedent for the typed-events option in #75 (already commented there with detail).

3. **Concrete memory stores** — guideline-backed and markdown-backed implementations of the memory store interface. Data Machine has parallel implementations of the same shape (`DiskAgentMemoryStore`, `GuidelineAgentMemoryStore`). See companion proposal: \"agents-api-default-stores companion plugin\" — separate issue to follow.

4. **Concrete CPT-backed session store** — implements the conversation transcript contract. Same default-stores question applies.

5. **Provider abstraction** — `WP_Agent_Provider` interface, `WP_Agent_Provider_Factory`, `WP_Ai_Client_Provider`. **Canonical's README explicitly excludes provider code** (delegates to `wp-ai-client`). The second extraction's provider classes stay outside the substrate as the host's adapter — this is the right boundary, no convergence needed here.

### Same idea, different name

Convergence means picking one name and migrating the other:

| Second extraction | Canonical | Notes |
|-------------------|-----------|-------|
| `WP_Agent_Conversation_Store` (interface) | `ConversationTranscriptStoreInterface` | Same shape, different namespace |
| `WP_Agent_Memory_Store` (interface) | `AgentMemoryStoreInterface` | Same shape, canonical's adds workspace fields |
| `WP_Agents_Registry` | `WP_Agents_Registry` | Both exist; merge to canonical |
| `WP_Agent` (value object aspects) | `WP_Agent` (value object) | Both exist; canonical's is already the thin shape |
| `WP_Agent_Message`, `WP_Agent_Tool_Call`, `WP_Agent_Tool_Result` | `AgentMessageEnvelope`, `Tools/ToolCall`, `Tools/ToolExecutionResult` | Comparable; canonical wins on namespacing |

## Convergence PR sequence

In order, smallest to largest:

1. **Lift typed lifecycle events into canonical** (`src/Runtime/Events/`). Parallel implementation can switch to `use AgentsAPI\\AI\\Runtime\\Events\\…` once landed. Resolves #75. **Small.**

2. **Land conversation lock/unlock on `ConversationTranscriptStoreInterface`** (#74). Both extractions need this for long-running loops; canonical defines the contract once. **Small.**

3. **Land cross-site A2A caller context** (#76). Substrate defines `WP_Agent_Caller_Context` + the header convention. **Medium.**

4. **Default-stores companion plugin** — extract the two pairs of parallel memory store impls (guideline-backed, markdown/disk-backed) plus the CPT session store into `agents-api-default-stores`. Removes duplication; gives outside adopters working stores from day one. **Medium**, separate issue.

5. **Refactor the second extraction's `WP_Agent` to thin value object + `AgentConversationLoop` composition.** All current behavior of the heavy base class is reachable through the loop's adapter slots: provider via the runner adapter, memory via the store adapters, transcript via the persister adapter, lifecycle via the typed events from step 1, compaction via the existing `AgentConversationCompaction` class, async/queued via the `Queued` typed event. **Large.** The architectural lift.

6. **Replace local interface declarations with canonical imports** in the second extraction. Drop `WP_Agent_Conversation_Store`, `WP_Agent_Memory_Store`, `WP_Agent_Provider` (provider stays as a host-side adapter, just stops being declared as a substrate interface). **Small** mechanical PR after step 5.

7. **Vendor canonical** in the second extraction via git subtree at the original `agents-api/` path. The mu-plugin package becomes the host-side adapter only. **Small.**

## Verification — non-regression on every concrete agent

The second extraction has many concrete `WP_Agent` subclasses already running in production (block editing, site building, P2 chat, reader chat, support, orchestrator, internal tooling, workflow agents, and more). Each one is a risk surface for the refactor in step 5.

The convergence cannot land without a verification story. Proposed gates:

- **Contract tests against every concrete agent.** A test harness that instantiates each subclass, runs a fixed prompt + tool sequence against a recorded provider, and asserts the produced messages, tool calls, and final result match a recorded baseline. Lives in the consumer (the second extraction), runs in CI on every convergence PR. Recordings produced from the current heavy `WP_Agent` before any refactor.

- **Sandboxed shadow runs.** For the higher-traffic agents (chat-facing ones), route a fraction of real production traffic through both the legacy and refactored paths, diff the produced transcripts, alert on divergence. Ramp-up gated.

- **Per-feature smoke abilities.** Each agentic feature (block edit, site build, P2 chat, reader chat, support search, etc.) gets a one-shot smoke test that runs the user-visible feature end-to-end. Runs in pre-merge CI plus a daily watcher.

- **Compatibility shim during migration.** The legacy heavy `WP_Agent` stays available under its current name and lazy-delegates to the new thin value object + loop composition for one release cycle. Concrete agents migrate one at a time.

- **Telemetry watch on production rollout.** Tool-call success rate, transcript length, completion-status distribution, time-to-first-token monitored before/after each rollout slice. Auto-rollback gate on regression.

The contract test harness is the gating dependency for step 5 — it should land before the refactor starts, not after.

## Out of scope

- Provider-specific code stays outside canonical (delegated to `wp-ai-client`).
- Concrete admin UI, REST routes, and product workflows stay in the consumer (boundary already in canonical's README).
- Episode detection, context-tree variable substitution, and other above-the-substrate memory engineering primitives stay in the consumer for now. They're candidates for follow-up substrate primitives later, after the convergence settles.

## AI assistance

- **AI assistance:** Yes
- **Tool(s):** Claude Code (Opus 4.7)
- **Used for:** Side-by-side inventory of the two parallel extractions, drafting the convergence sequence, and identifying the regression-test gating dependency.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.