Skip to content

Releases: cognesy/instructor-events

v2.2.0

18 Mar 23:37

Choose a tag to compare


title: 'v2.2.0'

What's New

v2.2.0 adds deeper telemetry across the stack. More parts of the system now share stable IDs,
correlation data, and smaller event payloads, so it is easier to trace one run from agent control,
through structured output and inference, down to HTTP.

There are also a few user-facing changes: hub can now filter examples by tag, streamed tool events
in agent-ctrl are more accurate, and agent stop handling is more predictable.

Agents And Agent Control

Telemetry from runs, tools, and subagents

agent-ctrl now assigns one executionId to each run and keeps it through the whole bridge flow.
That run can now be traced more clearly in events and in the final response.

Streamed tool events for Claude Code and Gemini were also reworked. Tool-use events now wait for the
matching tool result, so they report the real tool name, input, output, and error state instead of a
placeholder.

Cleaner stop handling in agents

AgentLoop now checks whether execution should stop before the first step and again after beforeStep.
This lets hooks stop a run cleanly without forcing another model or tool cycle.

When multiple stop signals exist, agents now picks the highest-priority reason instead of the first
one that happened to be recorded. That makes the final stop reason more consistent.

Tool calls and subagents also carry stable IDs and trace data, which makes it easier to connect parent
and child work in telemetry and logs.

Structured Output, Inference, And HTTP

End-to-end telemetry in instructor and polyglot

instructor now emits structured-output events with stable request, execution, and attempt IDs.
Streaming and non-streaming runs also report the same kind of response summary data, including finish
reason, token usage, and tool-call counts.

polyglot now carries telemetry correlation from InferenceRequest down into the underlying
HttpRequest. Stream finalization was also tightened up, so completed and failed streamed runs update
execution state more reliably.

Better request correlation in HTTP layers

http-client and http-pool now keep requestId attached more consistently, including pooled
responses and streamed HTTP events. This makes it easier to match a response or stream event back to
the request that created it, and to keep one trace chain across higher-level and lower-level layers.

Failure events in instructor and polyglot were also cleaned up so they report smaller, safer
summaries instead of large raw payloads.

Hub

hub list now supports --tag and --tags, and examples can carry normalized tag metadata. This
makes it easier to find examples by topic without scanning the whole catalog.

Upgrade Notes

  • If you read raw event payloads from agent-ctrl, agents, instructor, polyglot, http-client, or http-pool, review them before upgrading. Several events now include new IDs, summary fields, and different payload shapes.
  • In agents, the final stop reason may differ from earlier releases because stop signals are now resolved by priority.
  • In agent-ctrl, some streamed tool events are emitted later than before, but they now contain the actual tool result data.

v2.1.0

16 Mar 19:27

Choose a tag to compare


title: 'v2.1.0'

What's New

SessionRuntime::create() — single entry point for session creation

SessionRuntime now exposes a create(AgentDefinition $definition, ?AgentState $seed = null) method
that handles the full session creation lifecycle: instantiation, hook processing, persistence, and
event emission — all in one call.

Before:

$stateFactory = new DefinitionStateFactory();
$sessionFactory = new SessionFactory($stateFactory);
$session = $repo->create($sessionFactory->create($definition));

After:

$session = $runtime->create($definition);

The new method runs through the same hook and event pipeline as execute(), so session controllers
fire consistently for both creation and updates.

Dedicated BeforeCreate / AfterCreate hook stages

The AgentSessionStage enum gains two new cases: BeforeCreate and AfterCreate.

During SessionRuntime::create(), hooks fire in this order:

  1. BeforeCreate — create-only pre-persist logic (e.g. set defaults, assign IDs)
  2. BeforeSave — shared pre-persist logic (fires on both create and execute)
  3. persist
  4. AfterSave — shared post-persist logic (fires on both create and execute)
  5. AfterCreate — create-only post-persist logic (e.g. send notifications)

The execute() pipeline is unchanged — it continues to fire only BeforeSave / AfterSave.
This layered approach (inspired by Eloquent's creating/saving/saved/created events)
lets hooks distinguish between first-time creation and subsequent updates.

SessionFactory is now injectable

SessionRuntime accepts an optional ?SessionFactory constructor parameter. It defaults to
new SessionFactory(new DefinitionStateFactory()) when omitted, so existing call sites are
unaffected — but custom state factories can now be injected for testing or advanced use cases.

CanManageAgentSessions contract updated

The CanManageAgentSessions interface now includes create():

interface CanManageAgentSessions
{
    public function create(AgentDefinition $definition, ?AgentState $seed = null): AgentSession;
    public function listSessions(): SessionInfoList;
    public function getSessionInfo(SessionId $sessionId): AgentSessionInfo;
    public function getSession(SessionId $sessionId): AgentSession;
    public function execute(SessionId $sessionId, CanExecuteSessionAction $action): AgentSession;
}

When to use SessionFactory + repo directly

SessionFactory and SessionRepository::create() remain available for the one case where
you already have a fully constructed AgentSession — forking. ForkSession returns a
concrete session instance, so you persist that branch via $repo->create($forked) rather
than going through SessionRuntime::create().

v2.0.0

13 Mar 19:49

Choose a tag to compare


title: 'v2.0.0'

What's New

v2.0 is a ground-up rework focused on performance, type safety, and a tighter API surface.

  • Faster, leaner — streaming is more memory efficient, execution is lazy by default,
    and internal code paths have been consolidated.
  • Tighter APIs — both Instructor and Polyglot have cleaner, more type-safe public APIs
    with explicit fields instead of mode-based configuration.
  • More reliable — extensive unit, feature, integration tests and benchmarks back this
    release. A substantial number of bugs have been fixed across the stack.
  • Agent building blocks — new cognesy/agents package for custom agents, and an expanded
    cognesy/agent-ctrl to interact with CLI coding agents from PHP.

Breaking Changes

  • Instructor's public API centers on StructuredOutput, StructuredOutputRuntime,
    PendingStructuredOutput, StructuredOutputResponse, and StructuredOutputStream.
  • Polyglot uses explicit LLM API fields (responseFormat, tools, toolChoice) instead
    of output modes. Streaming moves to stream()->deltas().

Instructor

  • Execution flows through StructuredOutputRuntime, with lazy execution via PendingStructuredOutput.
  • Streaming is Instructor-owned: StructuredOutputStream exposes responses(), partials(),
    and sequence(). StructuredOutputStreamState accumulates state internally.
  • Configuration, validation, transformation, deserialization, and extraction are explicit
    parts of the runtime rather than scattered across older code paths.

Polyglot

  • InferenceRuntime and EmbeddingsRuntime sit behind the Inference and Embeddings facades.
  • New inference drivers: openai-responses, openresponses, glm, qwen.
  • Built-in pricing via Pricing\Cost, per-model pricing objects, and cost calculators.
  • Polyglot handles raw transport — structured value ownership belongs to Instructor.

Agents (cognesy/agents)

New package. Building blocks for custom agents: AgentLoop, AgentBuilder, hooks, guards,
templates, subagents, skills, and SessionRuntime for persisted workflows.

Compose agents from capabilities like bash, file tools, structured outputs, summarization,
self-critique, planning, execution history, and broadcasting.

Two built-in drivers: ToolCallingDriver (native tool-calling APIs) and ReActDriver
(Thought/Action/Observation loops).

AgentCtrl (cognesy/agent-ctrl)

Unified PHP API for interacting with CLI coding agents — Claude Code, Codex, OpenCode,
Pi (new), and Gemini (new).

  • AgentCtrl::make() and dedicated builders (::codex(), ::openCode(), ::pi(),
    ::gemini()) return normalized AgentResponse objects.
  • Streaming callbacks, session resume/continue, typed IDs (AgentSessionId,
    AgentToolCallId), and AgentCtrlConsoleLogger for observability.

Migrating from v1.x

  • Instructor: use ->get(), ->response(), and ->stream(). For partial snapshots,
    switch to stream()->responses(), stream()->partials(), or stream()->sequence().
  • Polyglot: replace mode-based JSON/tool config with responseFormat, tools,
    toolChoice, and delta-based streaming.
  • See packages/instructor/docs/upgrade.md and packages/polyglot/docs/upgrade.md for details.

v1.22.0

20 Jan 19:39

Choose a tag to compare


title: 'v1.22.0'

Highlights

  • Agent builder and capability namespaces are reorganized into Cognesy\Addons\AgentBuilder\*, with agent templates in Cognesy\Addons\AgentTemplate\*.
  • Structured extraction is reworked with ExtractionInput, ResponseContent, and streaming-friendly ExtractingBuffer + PartialJsonExtractor.
  • Hub example discovery now supports configurable sources and grouping via YAML config files.

Breaking Changes

  • Agent builder, capabilities, and tool registry classes moved from Cognesy\Addons\Agent\* to Cognesy\Addons\AgentBuilder\*.
  • Agent template definitions, registries, and blueprints moved to Cognesy\Addons\AgentTemplate\*; AgentContract is now AgentInterface and fromConfig() returns an AgentInterface (no Result wrapper).
  • Task planning capability (UseTaskPlanning, Todo* classes) and LlmQueryTool were removed.
  • Instructor extraction contracts changed: CanExtractResponse::extract() now accepts ExtractionInput and returns an array, throwing on failure. CanExtractContent, CanParseContent, DataFormat, JsonParser, and ExtractingJsonBuffer were removed.

Addons / Agents

  • Agent builder moved to Cognesy\Addons\AgentBuilder\AgentBuilder with capabilities under Cognesy\Addons\AgentBuilder\Capabilities\*.
  • New SubagentProvider/SubagentDefinition contracts and EmptySubagentProvider; AgentTemplate\Registry\AgentRegistry implements SubagentProvider.
  • Agent template registry and definition flow now live under Cognesy\Addons\AgentTemplate\* with explicit blueprint exceptions.

Instructor

  • ResponseExtractor now consumes ExtractionInput and uses ResponseContent for tool-mode extraction.
  • Streaming extraction uses ExtractingBuffer and PartialJsonExtractor for more resilient partial JSON handling.

Hub

  • Example sources can be configured via config/examples.yaml (multiple source roots supported).
  • Example grouping and ordering can be configured via config/examples-groups.yaml (subgroup include/exclude rules).

Migration from v1.21.0

  • Update imports to Cognesy\Addons\AgentBuilder\* (including AgentBuilder, all Capabilities, and Capabilities\Tools).
  • Move agent templates and registries to Cognesy\Addons\AgentTemplate\* and update AgentContract implementations to AgentBuilder\Contracts\AgentInterface with fromConfig() returning an AgentInterface.
  • Remove task planning usage (UseTaskPlanning, Todo*) and LlmQueryTool references; replace with custom tools or direct inference calls.
  • Update custom extractors to CanExtractResponse::extract(ExtractionInput $input): array and throw ExtractionException (or any Throwable); call with ExtractionInput::fromResponse(...) or ExtractionInput::fromContent(...).
  • Replace any direct usage of ExtractingJsonBuffer/JsonParser/DataFormat with ExtractingBuffer and the new extractor chain.

v1.21.0

19 Jan 20:14

Choose a tag to compare


title: 'v1.21.0'

Highlights

  • StepResult pattern across Agent, Chat, ToolUse, and Collaboration with immutable steps and explicit continuation outcomes.
  • Continuation evaluation is unified around ContinuationEvaluation and ContinuationOutcome, with clearer stop reasons.
  • Retry policy handling is explicit for Inference and Embeddings (no more retryPolicy inside options).
  • Hub status persistence now tolerates malformed UTF-8 output instead of failing to write status data.

Breaking Changes

  • Continuation interfaces CanDecideToContinue, CanExplainContinuation, and CanProvideStopReason were removed. Custom criteria must implement CanEvaluateContinuation and return ContinuationEvaluation.
  • Error handling classes moved from Cognesy\Addons\StepByStep\Continuation to Cognesy\Addons\StepByStep\ErrorHandling.
  • retryPolicy is no longer accepted in options or LLMConfig options. Use explicit retry policy objects.
  • Continuation outcomes are no longer stored on step objects. Use StepResult or state accessors instead.

Agent, Chat, ToolUse, Collaboration

  • States now store StepResult collections and serialize them.
  • canContinue() reads from the last step result; mismatches between steps and step results now raise a logic error.
  • Message compilation supports summary and buffer sections for inference context.
  • Token usage is accumulated before continuation evaluation so usage limits are accurate.

StepByStep / Continuation

  • ContinuationCriteria composes CanEvaluateContinuation criteria and exposes evaluateAll() with aggregated outcomes.
  • Criteria classes return richer ContinuationEvaluation objects with explicit decisions and stop reasons.
  • New outcome helpers provide derived decision, resolver, and stop reason from evaluations.

Polyglot / Inference and Embeddings

  • InferenceRequest and EmbeddingsRequest now carry retry policies explicitly.
  • InferenceRequestBuilder and request builder traits expose withRetryPolicy().
  • PendingInference and PendingEmbeddings pull retry policies from requests rather than options.

Hub

  • Status JSON encoding now substitutes invalid UTF-8 bytes to avoid failures when saving example output.

Migration from v1.20.0

  • Update custom continuation criteria to implement CanEvaluateContinuation and return ContinuationEvaluation (replace CanDecideToContinue, CanExplainContinuation, CanProvideStopReason).
  • Update imports to the new error handling namespace: Cognesy\Addons\StepByStep\ErrorHandling\*.
  • Remove retryPolicy from LLM or request options. Use withRetryPolicy() on inference/embeddings builders or requests.
  • Replace any step-level continuation outcome access with state->continuationOutcome() or state->lastStepResult().

v1.20.0

18 Jan 19:22

Choose a tag to compare


title: 'v1.20.0'

Breaking Changes

Renames

  • ReverbAgentEventAdapterAgentEventEnvelopeAdapter
  • ToolRegistryContractToolRegistryInterface
  • DeterministicDriverDeterministicAgentDriver

Agent

  • AgentState now implements CanMarkExecutionStarted, CanMarkStepStarted, CanTrackExecutionTime
  • Added AgentState::recordStep(), AgentState::failWith(), AgentState::withAddedExecutionTime()
  • Agent::applyStep() and Agent::handleError() delegate to AgentState methods

StepByStep / Continuation

  • New CanProvideStopReason interface for criteria to provide explicit stop reasons
  • All continuation criteria implement CanProvideStopReason:
    • StepsLimitStopReason::StepsLimitReached
    • TokenUsageLimitStopReason::TokenLimitReached
    • ExecutionTimeLimit, CumulativeExecutionTimeLimitStopReason::TimeLimitReached
    • ErrorPolicyCriterionStopReason::ErrorForbade
    • FinishReasonCheckStopReason::FinishReasonReceived
    • ErrorPresenceCheck, RetryLimitStopReason::GuardForbade
  • ContinuationEvaluation includes stopReason field
  • Removed ContinuationCriteria::inferStopReason() (stop reasons now come from criteria directly)
  • New state contracts: CanMarkExecutionStarted, CanMarkStepStarted, CanTrackExecutionTime

Command Builders (agent-ctrl)

ClaudeCommandBuilder, CodexCommandBuilder, OpenCodeCommandBuilder:

  • stdbuf -o0 prefix now conditional (checks availability)
  • Skipped on Windows
  • Skipped when stdbuf not found on PATH (fixes macOS)
  • Override via COGNESY_STDBUF env var: 0 = disable, 1 = force

Polyglot / Inference

  • InferenceExecution::usage(): fixed double-counting of current attempt
  • InferenceResponse: added <think>...</think> tag parsing for reasoning content fallback
  • New ReasoningContentSplit data class
  • AnthropicBodyFormat: cache marking applies only to last message in sequence (was all messages)
  • DeepseekResponseAdapter: supports reasoning, analysis fields as alternatives to reasoning_content
  • Inference::with(): parameters now nullable (pass null to skip, was required empty values)
  • PendingInference::asJson(), asJsonData(): use proper JSON extraction with output mode

HTTP Client

  • CurlHandle::close(): removed curl_close() call (no-op since PHP 8.0, deprecated in PHP 8.5)

Instructor

  • StructuredOutputStream: fixed execution reference update during streaming to capture accumulated usage

v1.19.0

18 Jan 13:03

Choose a tag to compare

Release Notes - v1.19.0

Highlights

  • Cleaned inference attempt lifecycle and event ownership in Polyglot.
  • Fixed serialization and caching edge cases across inference requests/partials.
  • Structured output handling is more robust with safer validation and immutable models.

Breaking Changes

  • InferenceExecution::withNewResponse() renamed to withSuccessfulAttempt().
  • InferenceExecution::withFailedResponse() renamed to withFailedAttempt().
  • InferenceExecution::withFailedFinalizedResponse() removed.
  • InferenceAttempt::withFailedResponse() removed; create attempts via startAttempt() / InferenceAttempt::started().
  • Usage::accumulate() removed; use withAccumulated() for immutable usage totals.
  • ValidationResult::invalid() now accepts ValidationError|ValidationError[] only.
  • ResponseModel::setPropertyValues() removed; use withPropertyValues().

Fixes and Improvements

Polyglot

  • InferenceRequest::toArray() now serializes messages and response_format as arrays.
  • InferenceRequest::hasMessages() and withCacheApplied() use explicit emptiness checks.
  • PartialInferenceResponse::toArray() now serializes response_data, with clearer tool accumulation.
  • InferenceStream no longer double-dispatches completion events.
  • HandlesRequestBuilder::withToolChoice() accepts string|array.

Instructor

  • StructuredOutputStream reuses its generator and emits StructuredOutputStarted once.
  • Response validation captures thrown exceptions as ValidationResult::invalid().
  • Tool-call JSON encoding failures return Result errors instead of throwing.
  • ResponseModel::toArray() guards non-object instances; fluent methods return static.

Tests

  • Added coverage for attempt IDs, streaming completion events, serialization, validation failures, and ResponseModel immutability.

v1.18.4

17 Jan 20:15

Choose a tag to compare

Release Notes - v1.18.4

Highlights

  • YAML agent definitions with strict parsing, validation, and version checks.
  • Blueprint and capability registries for mapping definitions to implementations.
  • Definition loading and auto-discovery from files, directories, and .claude/agents.

New Features

Agent Definitions

  • Added AgentDefinition DTO with LLM, execution, tool allow/deny, capabilities, and metadata.
  • Added AgentDefinitionParser with strict key validation and version enforcement.
  • Added AgentDefinitionLoader for loading definitions from files/directories (recursive supported).
  • Added AgentDefinitionRegistry with auto-discovery and error collection.

Blueprint and Capability Registries

  • Added AgentBlueprintRegistry for alias-to-class resolution.
  • Added AgentDefinitionFactory to build agents from definitions via blueprints.
  • Added AgentCapabilityRegistry for instance/factory resolution.

Tests

  • Added unit tests for definition parsing/loading/registry and blueprint/capability registries.

v1.18.3

17 Jan 14:11

Choose a tag to compare

Release Notes - v1.18.3

Highlights

  • Tool discovery registry with metadata/full-spec layering for progressive tool discovery.
  • New tools tool for list/help/search of available tools without loading full specs.
  • Capability to wire tool registries into agents for dynamic tool catalogs.

New Features

Tool Registry

  • Added ToolRegistryContract and ToolRegistry for registering tool instances or factories.
  • Added ToolPolicy filtering for allow/deny tool lists.
  • Added metadata and full-spec resolution helpers to support progressive discovery.

Tools Tool

  • Added ToolsTool for list, help, and search actions (plus CLI-like command parsing).
  • Supports locale-aware metadata/full spec rendering via registry.

Agent Capability

  • Added UseToolRegistry capability for agent blueprints to expose registries as tools.

Tests

  • Added registry and tools discovery tests for metadata/full spec, search, and help flows.

v1.18.2

17 Jan 10:17

Choose a tag to compare

Release Notes - v1.18.2

Highlights

  • Continuation-safe agent state persistence with new serialization helpers.
  • MessageStore serialization is now round-trip safe and section-aware.
  • Metadata preservation fixes for slim agent state snapshots.

Behavior Changes

MessageStore toArray Structure

  • MessageStore::toArray() now returns a structured payload with sections and parameters instead of a flat messages list.
  • Use MessageStore::toFlatArray() to obtain the previous flat messages array format.

New Features

Agent Continuation APIs

  • Added AgentState::withUserMessage() for multi-turn continuation.
  • Added AgentState::forContinuation() to reset execution state (steps, cache, usage, timing) while preserving conversation history.

Continuation Serializer

  • Added ContinuationAgentStateSerializer with ContinuationSerializationConfig to persist multi-turn state with retention limits.
  • Supports truncation, tool-result omission, and tool-arg redaction while preserving _metadata.

Bug Fixes

Metadata Preservation

  • SlimAgentStateSerializer now emits _metadata (with metadata alias support) so tool calls/results survive round-trips.
  • MessageInput::fromArray() now accepts metadata as a fallback alias for _metadata.

Serialization Round-Trip

  • MessageStore serialization now round-trips sections, messages, and parameters without data loss.

Tests

  • Added round-trip tests for MessageStore and continuation serialization.
  • Added AgentState continuation tests covering reset semantics and message appending.