All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
Breaking
- Removed the reserved
persistencefield fromAgentix.Conversation.Config(documented as unused in 0.3.0; it was never consulted).Config.new/1now raises on a:persistencekey — persistence is configured at the application level only (config :agentix, :persistence), and ephemeral one-shots clean up viaAgentix.Persistence.delete_conversation/1.
[0.3.0] - 2026-07-07
Added
- Per-conversation
api_keyonAgentix.Conversation.Config— a string or a 0-arity resolver fun (re-evaluated on every model call) passed to the provider as a per-request option.nilkeeps ReqLLM's own key resolution. The Ecto persistence adapter's settings sanitizer drops it, so key material never lands in a durable row; a conversation revived from persisted settings alone is key-less and the host must re-pass a freshconfig:. Agentix.Conversation.stop/1— public verb to release an idle conversation's agent process without ending the conversation (persisted events remain; the nextensure_started/2revives it). Replaces hosts reaching intoAgentix.Registry/Agentix.ConversationSupervisorinternals.{:turn_failed, turn_ref, reason}live event — provider/stream failures now get their own terminal event carrying the reason. Previously they broadcast the same{:cancelled, turn_ref}as a user-initiated cancel, so consumers could not distinguish "your key/provider failed" (e.g. an auth rejection) from "you cancelled".
Changed
A per-conversation
api_keyresolver fun is now evaluated inside the monitored streaming task: a raising resolver fails the turn ({:turn_failed, …}) instead of crashing the conversation's agent process.The ETS persistence owner now starts unconditionally (previously only when ETS was the app-configured adapter), so ETS is usable in tests and tools regardless of the app default.
Config.persistenceis documented as Reserved: the agent persists through the application-level adapter only; the field was never consulted and the old doc implied otherwise.Agents now trap exits:
Conversation.stop/1and supervisor shutdown drain the in-flight callback before terminating, so an agent mid-write to durable persistence is never killed between statements (previously a stop could sever a checked-out DB connection mid-query).
Breaking
- New required
Agentix.Persistencebehaviour callbackdelete_conversation/1(implemented by both bundled adapters): removes a conversation and everything under it (events, summaries, tool calls, audit rows) — ephemeral one-shot tasks call it after reading usage so throwaway conversations never accumulate. Third-party adapters must implement it. - Turns that fail on a provider/stream error no longer emit
{:cancelled, turn_ref}— subscribe to{:turn_failed, turn_ref, reason}for that terminal.{:cancelled, …}is now exclusively user-initiated.
0.2.0 - 2026-06-25
Added
- Provider retry & backoff — a per-conversation
retrypolicy onAgentix.Conversation.Config(%{max_attempts, base_ms, max_ms}orfalse). Transient pre-stream failures (HTTP 429, 5xx, connection drops) are retried with exponential backoff + jitter, honoring aretry-afterheader (capped at 60s); 4xx and unrecognized errors fail fast. A failure after the first streamed token is never retried. Classification/backoff live in the new publicAgentix.Retry. Each retry emits a[:agentix, :turn, :retry]telemetry event. - Structured output — make the model return typed data conforming to a schema.
Pass
schema:toAgentix.Conversation.send_message/4(one-shot) or setresponse_formaton the config (default);schema: falseopts out per turn. The parsed object is surfaced viaAgentix.object/1and theAgentix.Chat:last_objectassign, and persisted in the assistant message'smetadata["object"](no migration). A schema turn is terminal (the tool loop is skipped).Agentix.Provider.ReqLLMbranches toReqLLM.stream_object/4. Agentix.Test.error/2,Agentix.Test.transport_error/1, and a:objectoption onAgentix.Test.completion/2for driving retry and structured-output scenarios with the mock provider.- New guide: Reliability & structured output.
0.1.0 - 2026-06-25
First public release.
Added
- Agent runtime — one event-sourced
:gen_statemper conversation (Agentix.Conversation), with non-blocking streaming turns, in-process tool execution, and mid-turn cancellation. Conversations are started on demand viaAgentix.Conversation.ensure_started/2and survive process death. - Provider seam —
Agentix.Providerbehaviour with a streaming + cancel + finalize contract;Agentix.Provider.ReqLLMadapts ReqLLM's canonical typed model and provider abstraction. - Tools & HITL — an explicit executor model (
:server,:human,:client,:provider) with gated approval, durable suspension intoawaiting_input, and a public, socket-independentAgentix.resolve/4(LiveView, webhook, job, or timeout). Suspended turns revive from durable state. - Hook pipeline — per-turn pre/post hooks (
Agentix.Hook), parallel append-only injections with a token reserve, halt semantics, and a per-chunk stream-transformer seam. - Compaction — reducer pipeline (tool-result stubbing, sliding window, async
cumulative summarization) gated by a token budget, behind a pluggable
Agentix.Tokenizerbehaviour (default char/4 heuristic, no extra dependency). - Persistence — the
Agentix.Persistencebehaviour with two adapters sharing one conformance suite:Agentix.Persistence.ETS(default, no database) andAgentix.Persistence.Ecto(Postgres, kill-and-resume, optional Oban-backed suspension expiry). Both LiveView and Ecto/Oban are optional dependencies. - Headless LiveView layer —
Agentix.Chat(usemacro +on_mountprojection of the live-event plane onto assigns, streamed deltas to a JS hook), optional ownableAgentix.Components, andmix agentix.gen.components/mix agentix.gen.migrationgenerators. - Live-event union — a typed event plane broadcast over
Phoenix.PubSub(Agentix.Notifierbehaviour;PubSubdefault,Noneno-op) consumable by any transport. - Test story —
Agentix.Testassertions and a scriptableAgentix.Test.MockProviderfor driving conversations deterministically with no API key. - Modern tooling: Credo, Dialyxir, Styler, ExCoveralls, MixAudit, ExDoc, and a
mix checkquality gate.