diff --git a/README.md b/README.md index 42bd9ed..ea793f8 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ If you're building a plugin that needs an AI agent — one that can hold a conve It's a small, focused WordPress package maintained by Automattic. Think of it as the layer that sits *underneath* your product: it owns the boring-but-important parts (agent identity, runtime contracts, tool mediation, sessions, transcripts, memory, workflow scaffolding), so your plugin can focus on what makes it special. -**What you get out of the box:** a way to register agents, a messaging channel base class that plugs into any transport, value objects for the agent lifecycle, contracts for tools and memory and consent, and lightweight workflow plumbing (spec, validator, runner skeleton, three abilities, an optional Action Scheduler bridge). +**What you get out of the box:** a way to register agents, a fallback provider-agnostic `agents/chat` runtime, a messaging channel base class that plugs into any transport, value objects for the agent lifecycle, contracts for tools and memory and consent, and lightweight workflow plumbing (spec, validator, runner, default `ability`, `agent`, `foreach`, and `parallel` step handlers, three abilities, and optional Action Scheduler-backed async branch execution). -**What you don't get — and shouldn't expect:** a concrete workflow runtime, durable run history, an editor UI, admin screens, or any provider-specific AI client. Those belong to your product. Agents API is the substrate, not the application. +**What you don't get — and shouldn't expect:** durable workflow history, a workflow editor UI, admin screens, or any provider-specific AI client. Those belong to your product. Agents API is the substrate, not the application. New here? Start with the [Introduction](docs/introduction.md) — it breaks down the core concepts and vocabulary in plain language — then browse the [developer documentation](docs/README.md). @@ -48,13 +48,13 @@ Agents API sits between tool/action discovery and product-specific automation. I - Tool source registration, parameter normalization, tool-call mediation, and execution result contracts. - Session and persistence contracts where they are provider-neutral. - Retrieved context authority vocabulary, context item shape, and conflict resolution contracts. -- Workflow spec value object, structural validator, in-memory registry, abstract runner with `ability` and `agent` step types, `Store` and `Run_Recorder` interfaces, optional Action Scheduler bridge, and three canonical abilities (`agents/run-workflow`, `agents/validate-workflow`, `agents/describe-workflow`). +- Workflow spec value object, structural validator, in-memory registry, runner with default `ability`, `agent`, `foreach`, and `parallel` step handlers, `Store` and `Run_Recorder` interfaces, optional Action Scheduler bridge and branch executor, and three canonical abilities (`agents/run-workflow`, `agents/validate-workflow`, `agents/describe-workflow`). - Runtime package workflow execution request/result contracts and the canonical dispatcher ability (`agents/run-runtime-package`) for consumer-owned package materialization and execution adapters. ## What Agents API Does Not Own - Provider-specific request code. `wp-ai-client` owns provider/model prompt execution. -- Concrete workflow runtimes, durable workflow / run history, scheduling adapters beyond the optional Action Scheduler bridge, workflow editor UI, and product-specific step types (`branch`, `parallel`, nested `workflow`). The substrate provides the contract surface; consumers ship the persistence and product UX. +- Durable workflow / run history, scheduling adapters beyond the optional Action Scheduler bridge and branch executor, workflow editor UI, and product-specific step types (`branch`, nested `workflow`). The substrate provides default in-process step execution plus an optional Action Scheduler path for async `parallel` branches; consumers ship the persistence and product UX. - Product UI such as admin pages, settings screens, dashboards, or onboarding. - Product CLI commands beyond generic substrate needs. - Public REST controllers in v1 unless they are separately designed. diff --git a/docs/channels-workflows-operations.md b/docs/channels-workflows-operations.md index 3bcf5c3..c73834a 100644 --- a/docs/channels-workflows-operations.md +++ b/docs/channels-workflows-operations.md @@ -64,6 +64,8 @@ array( The channel can consume either a single `reply` or assistant `messages` from the ability result. It stores a returned `session_id` before sending replies so delivery failures do not lose session continuity. `agents/chat` also exposes a canonical `run_id`; runtimes receive a generated `run_id` in the input when callers omit one, and responses include that same ID unless the runtime returns its own. +Agents API registers a default `agents/chat` runtime as a fallback at `wp_agent_chat_handler` priority 1000. The fallback resolves provider and model from the chat input first, then from the registered agent's default config, and returns a validation error when either value is missing. Consumer runtimes normally register their own handler at the default priority 10, so they win before the fallback runs. + ## Chat run control Agents API owns the generic run-control ability contracts and default run-control storage. Every `agents/chat` run receives a `run_id`, stores status when a session is known, accepts best-effort cancellation, and accepts queued follow-up messages. Runtimes may override the hooks below only when they can provide stronger behavior such as immediate provider aborts or a custom queue worker. @@ -224,7 +226,7 @@ Bridge authorization is intentionally separate from queue state. Connectors can ## Workflow specs and validation -Workflows are deterministic recipes composed of inputs, triggers, and steps. Agents API provides the spec value object, structural validator, in-memory registry, runner skeleton, store/recorder interfaces, optional Action Scheduler bridge, and canonical abilities. It does not ship a concrete durable workflow runtime, editor UI, product step types, or run-history database. +Workflows are deterministic recipes composed of inputs, triggers, and steps. Agents API provides the spec value object, structural validator, in-memory registry, runner, default step handlers, store/recorder interfaces, optional Action Scheduler bridge and branch executor, and canonical abilities. It does not ship a durable workflow runtime, editor UI, product-specific step types, or run-history database. `WP_Agent_Workflow_Spec_Validator::validate( array $spec ): array` performs structural validation only: @@ -232,7 +234,7 @@ Workflows are deterministic recipes composed of inputs, triggers, and steps. Age - `inputs`, when present, must be a map; - `steps` must be a non-empty list; - each step needs an `id` and `type`; -- built-in step types are `ability` and `agent`; +- built-in step types are `ability`, `agent`, `foreach`, and `parallel`; - consumers can extend known step types through `wp_agent_workflow_known_step_types`; - `wp_action` and `cron` trigger shapes are checked; - forward or unknown `${steps..output.*}` binding references are reported. @@ -257,8 +259,12 @@ Default step handlers: - `ability`: calls a registered Abilities API ability with resolved `args`. - `agent`: calls the canonical `agents/chat` ability with `agent`, `message`, and optional `session_id`. +- `foreach`: runs nested `steps` once for each resolved item in process. +- `parallel`: fans out either role-scoped `branches` or mapped `items`, collects branch outputs, and optionally runs one aggregator branch. + +The default `parallel` handler uses `wp_agent_workflow_step_executor` as its concurrency seam. When an executor is available, it dispatches branches out of band and returns a `_suspend` directive so the run can resume after reconciliation. Agents API ships an Action Scheduler branch executor that is selected when `as_enqueue_async_action()` exists; it enqueues one async action per branch, raises branch-specific Action Scheduler concurrency while branches are in flight, and triggers loopback runners for faster drain. Without Action Scheduler or a caller-supplied executor, `parallel` falls back to synchronous in-process branch execution. -Consumers extend the runner through the constructor or the `wp_agent_workflow_step_handlers` filter. Product-specific steps such as `branch`, `parallel`, or nested `workflow` belong in consumers. +Consumers extend the runner through the constructor or the `wp_agent_workflow_step_handlers` filter. Product-specific steps such as `branch` or nested `workflow` belong in consumers. Recorder behavior is conservative: `start()` runs before input validation, per-step `update()` calls follow state changes, and recorder-start failure returns a failed run result without executing steps. diff --git a/docs/remote-bridge-protocol.md b/docs/remote-bridge-protocol.md index 1c3de1e..a4e3cf3 100644 --- a/docs/remote-bridge-protocol.md +++ b/docs/remote-bridge-protocol.md @@ -2,7 +2,7 @@ Remote bridge clients are out-of-process processes that relay messages between an external surface and a WordPress agent runtime. They differ from direct `WP_Agent_Channel` subclasses because the client may be offline, webhook delivery may fail, and replies need a queue-first recovery path. -Agents API provides the generic PHP primitives for that protocol. It does not ship platform-specific clients, REST routes, product onboarding UI, or a chat runtime. See [Bridge Authorization And Onboarding](bridge-authorization.md) for the auth boundary. +Agents API provides the generic PHP primitives for that protocol and a fallback provider-agnostic `agents/chat` runtime. It does not ship platform-specific clients, REST routes, or product onboarding UI. Consumers can replace the fallback by registering their own `wp_agent_chat_handler`. See [Bridge Authorization And Onboarding](bridge-authorization.md) for the auth boundary. ## Relationship To Core Connectors diff --git a/src/Workflows/class-wp-agent-workflow-runner.php b/src/Workflows/class-wp-agent-workflow-runner.php index 06a9d43..4c0e137 100644 --- a/src/Workflows/class-wp-agent-workflow-runner.php +++ b/src/Workflows/class-wp-agent-workflow-runner.php @@ -7,8 +7,9 @@ * 1. Validate inputs against the spec's input schema (presence + type). * 2. Walk steps in order. For each step: * a. Resolve `${...}` bindings against `inputs` + earlier step outputs. - * b. Dispatch to a step-type handler (`ability` / `agent` ship by - * default; consumers register more via the handler map). + * b. Dispatch to a step-type handler (`ability`, `agent`, `foreach`, + * and `parallel` ship by default; consumers register more via the + * handler map). * c. Record the per-step outcome (status, output, error, timing). * d. If the step failed and the spec didn't opt into `continue_on_error`, * short-circuit the run. @@ -19,15 +20,14 @@ * - Branching, nested workflows. Step-handler map is the extension point * for those — a consumer can register a `branch` handler that runs a * sub-list, or a `workflow` handler that calls this runner recursively. - * - Real concurrency. The runner is synchronous and single-process; PHP - * ships no threads here. The `parallel` step type expresses *fanout - * orchestration* (declare N branches, propagate a shared immutable - * context to each, collect every branch output, and optionally run one - * aggregator branch over the collected outputs) — not parallel execution. - * Whether branches actually run on separate processes (Action Scheduler, - * sandboxed subprocesses, loopback) is a consumer-supplied executor - * concern; the substrate owns the scatter/collect/return contract (plus - * the optional aggregate pass), not the concurrency mechanism. + * - Unconditional concurrency. The default `parallel` handler owns fanout + * orchestration (declare N branches, propagate a shared immutable context + * to each, collect every branch output, and optionally run one aggregator + * branch over the collected outputs). Real concurrent branch execution + * happens when `wp_agent_workflow_step_executor` returns a branch executor. + * Agents API ships an Action Scheduler executor that is selected when + * `as_enqueue_async_action()` exists; without that or a caller-supplied + * executor, `parallel` falls back to synchronous in-process execution. * - Triggering. Triggers are wired separately * ({@see WP_Agent_Workflow_Action_Scheduler_Bridge} for cron, and a * consumer-registered listener for `wp_action`). The runner only