JidoGralkor.Plugin (jido_gralkor v1.1.0)

Copy Markdown View Source

Jido plugin that replaces Jido.Memory.BasicPlugin with Gralkor-backed memory. Claims the :__memory__ slot so it is the only memory plugin attached to the agent.

session_id is the current Jido thread id, read from agent.state[:__thread__].id. One Jido thread per Gralkor session — the capture buffer rotates naturally when the thread rotates, and concurrent agents for the same principal never collide on the buffer. group_id is sanitize_group_id(agent.id) since memory graph partitioning is per-principal.

Recall fires on ai.react.query: Gralkor is always called with the agent's group_id and the current thread's session id (or nil when no thread has committed yet — first query of a fresh agent, before the ReAct strategy's ThreadAgent.append runs inside @start). When a thread is committed, its session id is planted on the signal's tool_context so in-turn tool calls (e.g. MemorySearch) key on the same session; when it isn't, no session id is planted. The returned memory block (when present) is stashed on tool_context under :__gralkor_memory__ regardless of thread state. The plugin does not mutate :query — the recalled memory is delivered to the LLM by a request transformer at prompt-build time (see Jido.AI.Reasoning.ReAct.RequestTransformer and Jido.AI.PromptBuilder), keeping :query the user's actual words everywhere downstream (buffer, request store, capture).

Capture fires on ai.request.completed / ai.request.failed: the full request trace and assistant answer are normalised via JidoGralkor.Canonical.to_messages/3 into Gralkor's canonical [%Gralkor.Message{role, content}] shape and shipped to the server, which keeps the rolling conversation buffer keyed by session_id. Because nothing in the turn mutates :query to add harness context, canonicalisation doesn't strip envelopes — the user message it persists is the user's actual words. Capture is skipped if the thread isn't present (first-turn failure with nothing committed) or if the canonical message list is empty.

Recall failures are best-effort under the retry-ownership doctrine (see gralkor/TEST_TREES.md › Retry ownership): if the Vertex-upstream retries at the google-genai SDK exhaust, Client.recall/3 returns {:error, _} and the plugin logs a warning and continues the turn without :__gralkor_memory__. Retrying here would amplify load without a meaningful chance of success, and failing the turn would turn a memory outage into a user-facing outage. Capture failures still raise (Gralkor capture is server-side buffered and its retry lives in the capture buffer, not here — a raise from capture/3 means the server is unreachable, which is a different failure class).

Summary

Functions

Returns metadata for Jido.Discovery integration.

Returns the list of action modules provided by this plugin.

Returns the capabilities provided by this plugin.

Returns the plugin's category.

Returns the Zoi schema for per-agent configuration.

Returns the plugin's description.

Returns the plugin manifest with all metadata.

Returns the plugin's name.

Returns the OTP application for config resolution.

Returns the plugin specification with optional per-agent configuration.

Returns the requirements for this plugin.

Returns the schedules for this plugin.

Returns the Zoi schema for plugin state.

Returns the signal patterns this plugin handles.

Returns the signal routes for this plugin.

Returns whether this plugin is a singleton.

Returns the key used to store plugin state in the agent.

Returns the sensor subscriptions for this plugin.

Returns the plugin's tags.

Returns the plugin's version.

Functions

__plugin_metadata__()

@spec __plugin_metadata__() :: map()

Returns metadata for Jido.Discovery integration.

This function is used by Jido.Discovery to index plugins for fast lookup and filtering.

actions()

@spec actions() :: [module()]

Returns the list of action modules provided by this plugin.

capabilities()

@spec capabilities() :: [atom()]

Returns the capabilities provided by this plugin.

category()

@spec category() :: String.t() | nil

Returns the plugin's category.

config_schema()

@spec config_schema() :: Zoi.schema() | nil

Returns the Zoi schema for per-agent configuration.

description()

@spec description() :: String.t() | nil

Returns the plugin's description.

manifest()

@spec manifest() :: Jido.Plugin.Manifest.t()

Returns the plugin manifest with all metadata.

The manifest provides compile-time metadata for discovery and introspection, including capabilities, requirements, signal routes, and schedules.

name()

@spec name() :: String.t()

Returns the plugin's name.

otp_app()

@spec otp_app() :: atom() | nil

Returns the OTP application for config resolution.

plugin_spec(config \\ %{})

@spec plugin_spec(map()) :: Jido.Plugin.Spec.t()

Returns the plugin specification with optional per-agent configuration.

Examples

spec = MyModule.plugin_spec(%{})
spec = MyModule.plugin_spec(%{custom_option: true})

requires()

@spec requires() :: [tuple()]

Returns the requirements for this plugin.

schedules()

@spec schedules() :: [tuple()]

Returns the schedules for this plugin.

schema()

@spec schema() :: Zoi.schema() | nil

Returns the Zoi schema for plugin state.

signal_patterns()

@spec signal_patterns() :: [String.t()]

Returns the signal patterns this plugin handles.

signal_routes()

@spec signal_routes() :: [tuple()]

Returns the signal routes for this plugin.

singleton?()

@spec singleton?() :: boolean()

Returns whether this plugin is a singleton.

state_key()

@spec state_key() :: atom()

Returns the key used to store plugin state in the agent.

subscriptions()

@spec subscriptions() :: [tuple()]

Returns the sensor subscriptions for this plugin.

tags()

@spec tags() :: [String.t()]

Returns the plugin's tags.

vsn()

@spec vsn() :: String.t() | nil

Returns the plugin's version.