# poetry-agent API

The agent-interop gem: the MCP server (stdio exe and the Rack HTTP transport), its bundled assembly, the WebMCP runtime's Ruby side, and the origin-trial middleware.

## Poetry::Agent

poetry-agent: the agent-interop gem of the poetry family - the
surfaces through which agents reach the component contract, built
once (the registry) and projected many ways:

- {MCP::Server} - the boot-free `poetry-agent` MCP server (discover:
  list_components / describe_component / check / compose / build_page
  / get_skill) for coding agents in editors.
- {WebMCP} - the in-page runtime: rendered components' declared tools
  (`tool` declarations in poetry-core) registered with the browser's
  `document.modelContext` for the user's own agent (operate), plus the
  declarative-form path and the origin-trial delivery.
- {A2UI} - the registry projected as an A2UI catalog (the vocabulary
  an agent generates declarative UI against).
- {AGUI} - the Rails-side AG-UI client: an agent backend's event stream
  folded into chat frames and relayed as versioned Turbo Streams,
  with the component tools the browser executes advertised as the
  agent's frontend tools.

Both read the same committed registries; neither is a second source.

### .config

The gem's configuration (origin-trial tokens, registration budget).

### .configure

Yields the configuration for block-style setup.

### .root

Gem root (the directory containing lib/, exe/, app/).

## Poetry::Agent::MCP::Server

The server: constructed with the registry root (and the host's helper
names, so check knows the group/provider helpers - though the
registry's own "helpers" section now carries those boot-free).
icon_names: the active icon set's names, so the check tool validates
icon values by membership, not just shape. Everything read is the
live committed registry.

### .from_registry(root, helpers: nil, icon_names: nil, skills: {}, app_root: nil, recipes: [])

skills: skill name => a zero-arg callable returning the skill's
{relative path => content} file map (the get_skill tool).
Lazy because the usage skill is generated from the registry on
first fetch - server boot stays instant.

### #handle(request)

A JSON-RPC 2.0 request hash -> a response hash (or nil for a
notification, which gets no reply).

### #initialize(entries:, catalog:, blocks: {}, root: nil, skills: {}, app_root: nil, recipes: [])

app_root: the HOST app directory (where `bundle exec poetry-agent`
runs, i.e. Dir.pwd), so build_page's probe/direct steps can read
the app's config/theme. nil => the host is not inspected and those
steps degrade gracefully; the registry read (root) is unaffected.
recipes: registry-item SUMMARIES (content-free) from the owning
gem's RecipeItems projection - the exe passes them so this class
stays poetry-ui-free.

### #serve(input: $stdin, output: $stdout)

The thin stdio loop: newline-delimited JSON-RPC in, replies out.
A malformed line yields a parse error, never a crashed server.

## Poetry::Agent::MCP::HTTP

The MCP server over HTTP: a Rack app answering JSON-RPC 2.0 POSTs
(the Streamable HTTP transport's request/response half) with the
same pure {Server#handle} the stdio exe uses - one surface, two
transports. Mount it at the conventional same-origin `/mcp`, which
is where in-page bridges (WebMCP site MCP server packs among them)
look for a site's own MCP server.

Read-only by construction (every tool describes or verifies), so
exposing it is a discovery surface, not a mutation surface. The
Origin header is validated against the request's own host, so a
cross-site page cannot drive it through a visitor's browser.

### #call(env)

The Rack entry point.

### #initialize(server = nil)

## Poetry::Agent::MCP::Bundled

The server as the exe assembles it: the registry root defaults to
the bundled poetry-ui gem, poetry-lucide's icon names power check's
icon-membership tier, and poetry-ui's skills, helper names, and
recipes ride along when the gem is bundled - each a soft require,
so the same assembly serves a core-only host. ONE assembly for the
exe and the HTTP mount, so no surface can lag another.

### .icon_names

The lucide names, or nil for a host without poetry-lucide (check
then validates icon-name shape only).

### .server(root: nil, app_root: Dir.pwd)

## Poetry::Agent::WebMCP

The WebMCP runtime's Ruby side. The contract itself lives in
poetry-core (the `tool` declarations, their registry projection, and
the per-instance `webmcp:` payload a component root carries); this
module owns what only the runtime gem knows: the Stimulus controller
identifiers the JS registers, the controllers manifest that lets
core's attribute builder validate them, and origin-trial delivery.

Nothing here exposes a tool by itself - a rendered instance opts in
(`webmcp: "country"` on the helper call), and the registrar
controller registers that instance's declared tools with
`document.modelContext` on connect, aborting them on disconnect.

### .manifest_path

The committed controllers manifest (the JS surface of the two
controllers), merged into poetry-core's catalog by the engine so
use_stimulus / the Builder validate poetry--agent--* names exactly
like core's own.

## Poetry::Agent::WebMCP::OriginTrial

Rack middleware serving the `Origin-Trial` response header on HTML
responses, one token per browser trial (Chrome and Edge run
separate trials and issue separate tokens). Tokens come from
{Poetry::Agent::Config#origin_trial_tokens}; with none configured
the middleware is a pass-through, so it is always safe to mount.

Local development needs no token: enable the API through the
browser flag instead.

### #call(env)

The Rack entry point: appends the tokens to HTML responses.

### #initialize(app, tokens: nil)

## Poetry::Agent::Config

The gem's configuration. Every WebMCP surface is OFF until a rendered
instance opts in; the settings here shape delivery and budgets, never
exposure.

### .current

The process-wide configuration instance.

### #initialize

### #origin_trial_tokens

Origin-trial tokens the {OriginTrial} middleware serves in the
`Origin-Trial` response header (one per browser trial - Chrome and
Edge run separate trials). Empty by default: local development
enables the API through the browser flag instead.

### #origin_trial_tokens=(value)

Origin-trial tokens the {OriginTrial} middleware serves in the
`Origin-Trial` response header (one per browser trial - Chrome and
Edge run separate trials). Empty by default: local development
enables the API through the browser flag instead.

### #registration_budget

The per-page registration budget the registrar enforces: past
this many registered tools on one document, further registrations
are dropped with a console warning (each tool costs the agent
context; overlap confuses tool choice). Stored on poetry-core's
configuration, where the component contract reads it to put the
budget on every opted-in root - this accessor writes through.

### #registration_budget=(count)

Sets the per-page registration budget.

## Poetry

The poetry namespace.

## Poetry::Agent::A2UI

The A2UI surface: Google's declarative generative-UI format, where
an agent emits a flat component list against a client-owned catalog
and the client renders it with its own components. Two halves ship:

- {Catalog} projects Poetry's registry into an A2UI v1.0 catalog
  document, so any A2UI agent generates against Poetry's vocabulary
  and a renderer validates what arrives against the same document.
- The renderer: {Session} folds the envelope (`createSurface`,
  `updateComponents`, `updateDataModel`, `deleteSurface`) into
  {Surface}s, {Renderer} renders a surface through the host's view
  context with a catalog binding ({Catalogs::Basic} for the spec's
  basic catalog, {Catalogs::Native} for Poetry's own), {Streams}
  delivers changes as versioned Turbo Streams, and a submitted
  surface form becomes the spec's `action` message
  ({Session#action}). {Functions} holds the basic catalog's function
  set - the `formatString` grammar ({Expression}), the formatters,
  the validators behind `checks` ({Checks}) - which {Evaluator} runs
  for both catalogs.

### .catalogs

The catalog bindings a {Session} starts with: the spec's basic
catalog and Poetry's own, keyed by catalog id.

## Poetry::Agent::A2UI::Catalog

Projects the component registry into an A2UI v1.0 catalog: one
JSON Schema component per registry entry (the discriminator
`component: { const: Name }`, style axes as enums, options as typed
properties, slots as child references, the content block as `text`
or `children`, Button's `action`), the catalog's composition
instructions, and the `$defs` the envelope schema references. The
document obeys the v1.0 catalog rules: the allowed top-level keys
only, `$defs` holding exactly `anyComponent` and `anyFunction`,
external refs into `common_types.json` only.

### .component_name(path)

The catalog component name of a registry path (PascalCase of its
last segment).

### .from_registry(root = nil, **)

Builds the catalog from a registry root (the directory holding
`config/component_registry.yml`), or from the bundled poetry-ui
registry when no root is given.

Keyword arguments pass through to {#initialize} (`catalog_id:`,
`title:`, `description:`, `instructions:`, `exclude:`).

### .load_entries(root = nil)

Loads the registry entries under a root (the bundled poetry-ui
registry when no root is given).

### .skipped_option?(name)

### #catalog_id

### #component_name(path)

The A2UI component name of a registry path (`poetry/ui/alert_dialog`
becomes `AlertDialog`).

### #components

The component schemas by name.

### #functions

The functions the catalog declares (the basic catalog's set, which
the renderer implements).

### #initialize(entries:, catalog_id: DEFAULT_ID, title: "Poetry UI Catalog", description: "Poetry's component library as an A2UI catalog, projected from its registry.", instructions: DEFAULT_INSTRUCTIONS, exclude: [])

### #inline

The inline form a transport ships to an agent or a middleware
fetches at boot.

### #to_h

The catalog document (JSON Schema, string keys, components sorted
by name).

### #to_json(*)

## Poetry::Agent::A2UI::Catalogs

The catalog bindings a {Surface} renders through: how a catalog's
components reference their children, which of them are bound
inputs, and how each one renders with Poetry.

## Poetry::Agent::A2UI::Catalogs::Basic

The A2UI basic catalog (v1.0) rendered with Poetry: every one of
its components maps onto a library component or a plain element,
its enums onto the library's axes, its bound inputs onto named
form controls, and its `checks` onto native constraint
attributes where the browser can enforce them.

### #functions

### #id

### #inputs(component, scope)

The bound input of a component, if it is one.

### #references(component)

The child references of a component (ids, id lists, templates).

### #render(component, scope, renderer)

## Poetry::Agent::A2UI::Catalogs::Basic::Choice

A ChoicePicker's resolved options, binding, selection, and label.

### #label

Returns the value of attribute label

### #label=(value)

Sets the attribute label

### #options

Returns the value of attribute options

### #options=(value)

Sets the attribute options

### #path

Returns the value of attribute path

### #path=(value)

Sets the attribute path

### #selected

Returns the value of attribute selected

### #selected=(value)

Sets the attribute selected

## Poetry::Agent::A2UI::Catalogs::Native

Poetry's own catalog (the {Catalog} projection) rendered back
through the registry: a component name resolves to its registry
entry, style axes and options become constructor keywords, slot
properties drive the generated slot setters, `text` is the
content block, `children` and `child` nest, and a bound `value`
names the control for the surface form. The registry is the one
source: whatever it declares renders, nothing is hand-mapped.

### #by_name

### #entries

### #functions

### #id

### #initialize(entries: nil, id: Catalog::DEFAULT_ID)

### #inputs(component, scope)

### #references(component)

The child references: `child`, `children`, and every slot property.

### #render(component, scope, renderer)

## Poetry::Agent::A2UI::Checks

Evaluates a component's `checks`: each rule's condition (a binding
or a function call) yields a ValidationResult - `{ "valid",
"code", "message", "severity" }` - or a boolean; a failing rule
of error severity is a failure, carrying the result's message or
the rule's fallback.

### .failures(component, evaluator)

## Poetry::Agent::A2UI::Evaluator

Resolves dynamic values in a scope: a `{ "path" }` binding reads
the data model, a `{ "call", "args" }` invokes a registered
function with its arguments resolved first (a string argument with
`${}` blocks interpolates, an array resolves item by item), and
`@index` reads the collection index the scope carries. Problems
(an unknown function, a bad argument, a malformed expression)
resolve to nil and reach the `on_error` callback.

### #argument(value)

Resolves a function argument: like {#resolve}, plus strings
interpolate and arrays and plain objects resolve inside.

### #call(name, args, resolved: false)

Calls a function by name.

### #evaluate(node)

Evaluates a parsed expression node.

### #index

### #initialize(surface, scope = nil, on_error: nil)

### #interpolate(text)

Interpolates a `formatString` template.

### #resolve(value)

Resolves a component property: bindings and calls resolve,
everything else is a literal.

### #scope

### #stringify(value)

The string a value displays as (the spec's conversion rules: nil
is empty, containers are JSON, whole floats drop their fraction).

### #surface

## Poetry::Agent::A2UI::Expression

The `formatString` grammar: literal text with `${...}` blocks, each
block a data path, a literal, or a function call with named
arguments whose values are expressions again (a bare argument is
`value`); `\${` is a literal `${`. Parsing yields a plain tree the
{Evaluator} walks:

  [:template, nodes]           the whole string
  [:text, "literal text"]
  [:path, "/absolute"]         or a relative path
  [:literal, 12] / [:literal, "quoted"] / [:literal, true]
  [:call, "formatDate", { "value" => node, "format" => node }]

### .dynamic?(text)

### .parse(text)

## Poetry::Agent::A2UI::Expression::Parser

The recursive-descent parser.

### #initialize(source)

### #template

## Poetry::Agent::A2UI::Expression::SyntaxError

A malformed expression.

## Poetry::Agent::A2UI::Functions

The renderer's function registry: named functions an agent may
reference in a component's dynamic values and checks, each with the
declaration a catalog document publishes (`functions` and
`$defs.anyFunction`). {Functions.basic} holds the spec's basic
catalog set - the validators, the formatters, the boolean
combinators, `openUrl` - implemented from their descriptions;
`@index` is the evaluator's own system function.

### .basic

The basic catalog's functions.

### .number(value)

### .truthy?(value)

The boolean reading of a value: a ValidationResult by its
`valid`, strings by content, nil and false as false.

### #agent_callable?(name)

### #any_function

The catalog document's `$defs.anyFunction`.

### #call(name, args, evaluator)

Calls a function with resolved arguments.

### #declared?(name)

### #define(name, description:, returns:, params: {}, required: [], activation: false, # rubocop:disable Metrics/ParameterLists callers: "rendererOnly", &impl)

Declares a function.

### #initialize

### #names

### #schema

The catalog document's `functions` section.

## Poetry::Agent::A2UI::Functions::Basic

The basic catalog's set, from the spec's descriptions.

### .install(registry)

### .list

A boolean list argument (`and`, `or`).

## Poetry::Agent::A2UI::Functions::Definition

One declared function.

### #activation

Returns the value of attribute activation

### #activation=(value)

Sets the attribute activation

### #callers

Returns the value of attribute callers

### #callers=(value)

Sets the attribute callers

### #description

Returns the value of attribute description

### #description=(value)

Sets the attribute description

### #impl

Returns the value of attribute impl

### #impl=(value)

Sets the attribute impl

### #name

Returns the value of attribute name

### #name=(value)

Sets the attribute name

### #params

Returns the value of attribute params

### #params=(value)

Sets the attribute params

### #required

Returns the value of attribute required

### #required=(value)

Sets the attribute required

### #returns

Returns the value of attribute returns

### #returns=(value)

Sets the attribute returns

## Poetry::Agent::A2UI::Functions::Error

A missing function or a bad argument list.

## Poetry::Agent::A2UI::Markdown

The Markdown subset an A2UI Text component needs, rendered without
a Markdown dependency: ATX headings, paragraphs, bullet lists,
emphasis, strong, inline code, and links. Input is escaped first,
so agent text never reaches the page as markup.

### .render(text)

### .strip(text)

Strips the same markers instead of rendering them - the
fallback the basic catalog guide asks for when markup is unwanted.

## Poetry::Agent::A2UI::Pointer

JSON Pointer (RFC 6901) over plain Ruby documents, with A2UI's two
extensions: relative paths (no leading slash) resolve against a
collection scope, and an upsert writes through missing objects.

### .absolute(path, scope = nil)

Resolves a path against a scope: absolute paths pass through,
relative ones append to the scope (the root when no scope).

### .build(parts)

Joins tokens back into a pointer.

### .get(document, path)

Reads the value at a pointer; nil for any missing step.

### .tokens(path)

Splits a pointer into unescaped reference tokens; `""` and `"/"`
both name the whole document.

### .upsert(document, path, value)

Writes a value at a pointer (A2UI upsert semantics): missing
objects are created along the way, a nil value removes the key,
and the whole-document pointer replaces the document.

## Poetry::Agent::A2UI::Renderer

Renders one {Surface} to HTML through the host's view context,
dispatching each component to the surface's catalog binding. The
surface becomes a form when an `action_url` is given: bound inputs
are named by their absolute data-model pointer and every agent
action is a submit button, so a user action posts the surface's
current inputs plus the source component - the spec's "inputs sync
only on an action" contract, in Hotwire's native shape. The
wrapper carries the surface's version for the versioned Turbo
Stream replace.

Rendering never raises for an agent's mistake: an unknown
component, a dangling reference, a component the library refuses
to build, or an unsupported function renders nothing and lands in
{#warnings}.

### .element_id(surface_or_id)

### #action_url

### #aria_label(component, scope = nil)

### #blank

### #call

### #call_function(name, args, scope = nil)

Calls a catalog function; a problem warns and returns nil.

### #component(klass, attributes = {}, suffix: nil, **keywords, &)

Builds and renders a library component. Every instance gets a
render-stable `key:` (the surface, the component, its scope, and
a suffix for repeated instances), so Turbo morph pairs the same
logical element across updates and local state survives.

### #control_id(component, scope = nil)

### #current_key

### #error_for(component, scope = nil)

### #errors

### #initialize(surface, view:, action_url: nil, html: {}, errors: {})

### #input_name(path, scope = nil)

### #markdown(text)

### #render_children(reference, scope = nil)

Renders a child reference (an id, an id list, or a template).

### #render_component(component_id, scope = nil)

### #resolve(value, scope = nil)

### #stable_key(suffix = nil)

### #submit_attributes(component, scope = nil)

The attributes that make a button an agent action.

### #surface

### #text(value, scope = nil)

The display string of a dynamic value; a function problem warns.

### #view

### #warn(message)

Records a problem and renders nothing for it.

### #warnings

## Poetry::Agent::A2UI::Session

The renderer-side consumer of the A2UI envelope: applies
`createSurface`, `updateComponents`, `updateDataModel`, and
`deleteSurface` to a set of {Surface}s, answers what it cannot
honor with renderer-to-agent error messages, and turns a
submitted form into the spec's `action` message.

### #action(surface_id:, source:, values: {}, timestamp: Time.now.utc)

Turns a submitted surface form into the agent's `action`
message: bound input values are written to the data model first
(two-way binding syncs on an action), then the source
component's event context resolves against the updated model.
Returns nil when the source has no agent event (a local action,
or an unknown component), and an invalid action - no message,
`errors` by component key - when a `checks` rule fails.

### #apply(message)

Applies one envelope message. Returns the ids of the surfaces
it changed (a deleted surface counts); problems are recorded in
{#errors} and return no ids.

### #apply_activity(content)

Applies the A2UI messages an AG-UI `a2ui-surface` activity
carries (an `a2ui_operations`, `messages`, or `operations` list,
or one bare message).

### #apply_all(messages)

### #catalog_for(catalog_id)

### #catalogs

### #deleted

### #errors

### #initialize(catalogs: A2UI.catalogs, default_catalog: nil)

### #responses

### #surface(surface_id)

### #surfaces

## Poetry::Agent::A2UI::Session::Action

A user action, ready for the agent: the spec message plus the
AG-UI placement (`forwardedProps.a2uiAction.userAction`).

### #errors

Returns the value of attribute errors

### #errors=(value)

Sets the attribute errors

### #forwarded_props

### #message

Returns the value of attribute message

### #message=(value)

Sets the attribute message

### #surface

Returns the value of attribute surface

### #surface=(value)

Sets the attribute surface

### #to_h

### #valid?

## Poetry::Agent::A2UI::Streams

Delivers a {Session}'s surfaces as Turbo Streams: a surface's first
appearance appends into the container (when one is given), every
later change is a versioned replace of its wrapper (`vreplace`,
from the AG-UI relay: a stale version never overwrites a newer
one), and a deletion removes it. The host renders each surface
through the `render` callable (typically a {Renderer}).

### #apply(message)

Applies one message and returns the streams for what changed.

### #apply_all(messages)

### #initialize(session:, render:, container: nil, morph: true)

### #mark_seen(*ids)

Marks surfaces as already on the page (rendered server-side), so
their next change replaces instead of appending.

### #session

### #stream_for(id)

### #streams(ids)

The streams for a set of surface ids.

## Poetry::Agent::A2UI::Surface

One A2UI surface on the renderer side: its flat component list
(an adjacency list keyed by id, `root` at the top), its data
model, and a monotonic version the Turbo Stream delivery compares.
A surface belongs to a catalog binding, which knows how each
component references its children; the surface itself is
catalog-agnostic beyond that.

### #binding?(value)

### #catalog

### #catalog_id

### #component(component_id)

### #components

### #data

### #expand(reference, scope = nil)

Expands a child reference into `[id, scope]` pairs: an id array
keeps the scope, a template instantiates its component once per
item of the bound array with the item's pointer as the scope.

### #failures(on_error: nil)

Evaluates every rendered component's `checks` against the data
model, keyed the way an action names its source (`id`, or
`id@scope` inside a template).

### #function_call?(value)

### #id

### #initialize(id:, catalog:, catalog_id: nil, send_data_model: false, data: nil, components: [])

### #inputs

Bound input descriptors of the rendered tree, absolute paths only.

### #program

What a client-side evaluator needs to run the checks as the user
types: every checked component's rules with its bindings made
absolute for its scope, the bound inputs by absolute path with
their kinds, and the data model for paths no input carries.

### #read(path, scope = nil)

Reads a bound path in a scope.

### #resolve(value, scope = nil, on_error: nil)

Resolves a dynamic value in a scope: a `{ "path" => ... }` binding
reads the data model (relative paths against the scope), a
`{ "call" => ... }` function call runs through the catalog's
functions (see {Evaluator}), anything else is a literal.

### #root

### #send_data_model

### #source_key(component, scope = nil)

### #template?(value)

### #text(value, scope = nil, on_error: nil)

The string a resolved value displays as (the spec's conversion
rules: nil is empty, containers are JSON).

### #to_h

### #update_components(list)

Upserts components by id and validates the result. Returns the
validation errors (each `{ code:, path:, message: }`); a dangling
child reference is not one - streaming delivers children later.

### #update_data(path, value)

Applies an `updateDataModel` (upsert; nil removes; the root
pointer replaces the whole model).

### #version

### #walk(&)

Walks the rendered tree depth-first from the root, yielding each
`[component, scope]` in render order (templates instantiate once
per item; a cycle guard keeps the walk finite).

## Poetry::Agent::AGUI

The AG-UI surface: a Rails-side CLIENT of the Agent-User Interaction
protocol. An agent backend (any AG-UI integration, or a Ruby server)
streams events - text deltas, tool calls, state, activities, run
lifecycle, interrupts - and this module turns that stream into
server-rendered chat frames a Hotwire page updates through Turbo
Streams, the same pipeline the chat replay rig proves.

The pieces, each usable alone:

- {SSE} parses `text/event-stream` chunks into event hashes.
- {Client} POSTs a run to an AG-UI endpoint and yields its events.
- {RunInput} builds the `RunAgentInput` wire hash, and
  {.tool_descriptor} advertises a rendered component's declared
  tools as frontend-defined tools the browser executes.
- {Transcript} folds events into messages (Chat-shaped parts),
  shared state (JSON Patch), activities, the run status, pending
  client tools, and interrupts.
- {Relay} renders each change as a versioned Turbo Stream through a
  host-supplied row renderer, plus the client-tool bridge element
  the `poetry--agent--agui-client-tool` controller executes.

Nothing here calls a model: the agent is whatever the host points
the client at.

### .field(hash, name)

Reads a wire field from an event or message that may arrive
camelCased (the protocol) or snake_cased (a Ruby producer).

### .tool_descriptor(instance, definition)

The frontend-defined tool descriptor for one of a rendered
component's declared tools: the MCP `Tool` shape the registry
projects, renamed to AG-UI's `parameters` and prefixed with the
instance name exactly as the WebMCP registrar registers it, so a
call the agent makes is executable in the browser by name.

## Poetry::Agent::AGUI::Client

The HTTP client: POSTs a `RunAgentInput` to an AG-UI endpoint and
yields the streamed events as they arrive (stdlib Net::HTTP,
`text/event-stream`). One call is one run; the multi-run model
(client tools, interrupts) is the caller's loop over {Transcript}.

### #initialize(url:, headers: {}, open_timeout: 10, read_timeout: 120)

### #run(input, &)

Runs the agent and yields every event.

## Poetry::Agent::AGUI::Client::Error

Raised for a non-success HTTP status.

### #initialize(message, status:)

### #status

## Poetry::Agent::AGUI::JsonPatch

RFC 6902 JSON Patch over plain Ruby data (Hash / Array), with RFC
6901 JSON Pointer paths - what AG-UI's STATE_DELTA and
ACTIVITY_DELTA carry. Applies atomically: the document is deep-
copied first and the copy is returned, so a failing operation
leaves the caller's document untouched.

### .apply(document, operations)

Applies a patch and returns the patched copy.

### .get(document, path)

Reads the value at a JSON Pointer.

## Poetry::Agent::AGUI::JsonPatch::Error

Raised for an operation the document cannot take (an unknown
op, a missing path, a failed test).

## Poetry::Agent::AGUI::Relay

Turns transcript changes into Turbo Streams. The host supplies the
row renderer (its own partial or component: a message and its
version in, the row's HTML out - the row must carry
`data-version`), the target id scheme, and the container new rows
append to. The relay stays view-free.

Client tools ride the same channel: when a run ends with tool
calls the browser must execute, {#client_tool_streams} appends
one bridge element per call; the `poetry--agent--agui-client-tool`
controller executes it through the registrar and POSTs the result
to the continue URL, whose response streams the next run.

### #apply(event)

Applies an event and answers the Turbo Streams it produced: an
append for a message's first appearance (when a container is
set), then the update action for every change.

### #client_tool_streams(continue_url:, container: @container)

Bridge elements for every pending client tool call.

### #initialize(transcript:, render:, container: nil, target: ->(message) { "row-#{message.id}" }, # rubocop:disable Metrics/ParameterLists action: "vreplace", append_render: nil, morph: false)

### #mark_seen(*ids)

Marks message ids the page already renders, so their next change
is an update rather than an append (server-rendered history).

### #stream_for(id)

The stream for one message id (nil when the message is unknown).

### #transcript

## Poetry::Agent::AGUI::RunInput

Builds the `RunAgentInput` wire hash an AG-UI agent accepts:
camelCased keys, messages in the protocol's shapes, the
frontend-defined tools, context entries, state, forwarded props,
and the resume entries that answer interrupts.

### .build( # rubocop:disable Metrics/ParameterLists -- one keyword per RunAgentInput field thread_id:, messages:, run_id: SecureRandom.uuid, tools: [], context: [], state: {}, forwarded_props: {}, parent_run_id: nil, resume: nil)

### .resume_entry(interrupt_id, status: nil, payload: nil)

A resume entry answering an interrupt.

### .tool_message(tool_call_id, content, error: nil, id: SecureRandom.uuid)

A tool-result message answering a tool call the browser ran.

### .user_message(content, id: SecureRandom.uuid)

A user message.

## Poetry::Agent::AGUI::SSE

A `text/event-stream` parser for AG-UI: every event is a JSON
object on one or more `data:` lines, terminated by a blank line.
Incremental (feed chunks as they arrive) and tolerant of comments,
`event:` / `id:` / `retry:` fields, and CRLF.

### .parse(source, &block)

Parses a complete stream (a String or anything responding to
`each` with chunks) and yields every event.

## Poetry::Agent::AGUI::SSE::Parser

The incremental parser.

### #errors

Lines that carried data the parser could not read as JSON.

### #feed(chunk, &)

Feeds a chunk and yields each completed event.

### #finish(&)

Flushes a trailing event that lacked its blank line.

### #initialize

## Poetry::Agent::AGUI::Transcript

Folds an AG-UI event stream into what a chat page renders: the
messages in order, each assistant message as Chat-shaped parts
(`{kind: :text, text:}`, `{kind: :reasoning, text:}`,
`{kind: :tool, name:, input:, output:, state:, tool_call_id:}`),
the shared state (snapshots and JSON Patch deltas), activities,
the run's status, its interrupts, and the tool calls the browser
must execute before the next run.

Every change bumps {#version}, and {#apply} answers the ids of the
messages it touched, so a relay re-renders exactly those rows with
a monotonic version the page's versioned replace honors.

### #activities

Activities by message id: `{ "type" => ..., "content" => ... }`.

### #apply(event)

Applies one event.

### #apply_all(events)

Applies every event of a stream.

### #client_tools

The frontend-defined tool names the browser executes.

### #custom_events

RAW and CUSTOM events, in order.

### #ended?

### #error

The run error, if any: `{ message:, code: }`.

### #frame(id)

The render-ready frame of one message.

### #initialize(client_tools: [])

### #interrupted?

### #interrupts

The open interrupts (string-keyed hashes as on the wire).

### #message(id)

### #messages

The messages in arrival order.

### #messages_for_input

The messages as the next run's `RunAgentInput.messages`: user
and assistant messages (assistant tool calls in the protocol's
`toolCalls` shape) and a tool message for every finished tool
call; reasoning and activities stay client-side, as the
protocol says.

### #pending_client_tools

Tool calls to client tools awaiting execution:
`{ tool_call_id:, name:, input:, message_id: }`.

### #resolve_client_tool(tool_call_id, content, error: nil)

Marks a client tool call as executed and records its result, so
the next run's input carries the tool message.

### #run

The run: `{ thread_id:, run_id:, status:, interrupts:, error:, result: }`;
status is :idle, :running, :finished, :interrupted, or :error.

### #state

The shared state after the last snapshot / delta.

### #unknown_events

Event types this transcript did not understand.

### #version

A monotonic clock over every applied change.

## Poetry::Agent::AGUI::Transcript::Message

One message. `role` is the protocol's ("user", "assistant",
"tool", "activity", ...); `parts` is the render-ready list.

### #id

Returns the value of attribute id

### #id=(value)

Sets the attribute id

### #parts

Returns the value of attribute parts

### #parts=(value)

Sets the attribute parts

### #role

Returns the value of attribute role

### #role=(value)

Sets the attribute role

### #version

Returns the value of attribute version

### #version=(value)

Sets the attribute version

## Poetry::Agent::AGUI::TurboStream

Turbo Stream builders for the relay: plain strings, no view
context needed. `vreplace` is the versioned replace the runtime
installs on Turbo (`registerPoetryAgent`) - it applies a frame
only when its `data-version` is newer than the row's, so an
out-of-order delivery can never paint an older state over a
newer one.

### .append(target, html)

### .build(action, target, html = nil, method: nil)

### .remove(target)

### .replace(target, html)

### .sse(html)

One SSE frame carrying the streams (newlines folded, as Turbo's
stream source expects one `data:` line).

### .vreplace(target, html, morph: false)

## Poetry::Agent::Engine

The Rails engine: merges the WebMCP controllers manifest into
poetry-core's catalog (so `webmcp:` roots validate at render), serves
the runtime JavaScript through the importmap-first channel, and
mounts the origin-trial middleware. Loading the gem is the only
integration step; the host imports `@poetry/agent` beside
`@poetry/controllers`.

## Poetry::Agent::MCP

The MCP server projecting the component contract
over Model Context Protocol so an agent in Claude Code / Cursor queries
the LIVE registry and runs the linter as a tool. Thin - it projects the
surfaces already built (Registry + LlmsText + Check), never a second
source. Read-only, progressive-disclosure (brief|detailed|full), and
verdict-returning (check returns per-finding pass/fail).

Two transports, one server: newline-delimited JSON-RPC 2.0 over stdio
(the `poetry-agent` exe; own the supply chain - no MCP SDK dependency)
and POST JSON-RPC over HTTP ({HTTP}, for the same-origin `/mcp` mount
in-page bridges read). {Server#handle} is a pure request->response
function (testable without either transport); {Server#serve} is the
stdio loop; {Bundled} is the one assembly both transports share.

v1 is the read/verify surface. The heavier roadmap - verify_screen
running the eval gate array, component:// artifact resources, tag
browsing, SSE streaming - is maturity-gated and NOT in this cut.