Releases: openintent-ai/openintent
v0.17.0
OpenIntent v0.17.0
Released: 2026-03-24
RFC-0026: Suspension Propagation & Retry
This release closes the three gaps left open by RFC-0025 (Human-in-the-Loop Intent
Suspension, v0.16.0): how suspension propagates through containers (intent graphs,
portfolios, plans, workflows), how agents can re-notify operators who don't respond,
and how downstream workflow phases observe upstream suspension.
Highlights
Container Propagation Rules
Five normative rules define how suspended_awaiting_input spreads through the
protocol's container hierarchy:
- Intent graph — A suspended child intent blocks all dependents from proceeding.
The parent aggregate status becomessuspended_awaiting_input. - Portfolio — The portfolio aggregate gains
has_suspended_members(bool) and
suspended_member_count(int). Two new events are emitted:
portfolio.member_suspendedandportfolio.member_resumed. - Plan / Task — When an intent suspends, its corresponding plan task transitions
toblockedwithblocked_reason: "intent_suspended"andsuspended_intent_id.
Plan progress gains asuspended_taskslist. The mirror is bidirectional: when the
intent resumes, the task unblocks automatically. - Workflow — Downstream phases that declare inputs from a suspended upstream phase
receiveUpstreamIntentSuspendedErrorat claim time rather than a generic failure.
Workflow progress gains asuspended_phaseslist. - Deadline — The suspension deadline governs expiry. It MUST NOT exceed the
portfoliodue_beforeconstraint if the intent is a portfolio member.
Human Re-Notification: HumanRetryPolicy
A new dataclass for configuring automatic re-notification when operators don't respond
to a suspension within the initial timeout_seconds window.
from openintent import HumanRetryPolicy, EscalationStep
policy = HumanRetryPolicy(
max_attempts=3,
interval_seconds=3600, # 1 hour between attempts
strategy="exponential", # fixed | linear | exponential
escalation_ladder=[
EscalationStep(
attempt=2,
channel_hint="slack",
notify_to="manager@example.com",
),
EscalationStep(
attempt=3,
channel_hint="sms",
notify_to="+15551234567",
),
],
final_fallback_policy="escalate", # fail | escalate | auto_resume | skip
)On each re-notification attempt the SDK:
- Re-fires
@on_input_requestedhooks - Emits
intent.suspension_renotifiedevent - Fires
intent.suspension_escalatedwhen an escalation ladder step is reached - Applies
final_fallback_policyonce all attempts are exhausted
EscalationStep
EscalationStep(attempt=2, channel_hint="slack", notify_to="manager@example.com")Backwards-compatible field aliases: after_attempt, channel, notify.
Three-Level Policy Cascade
Retry policy resolution follows a cascade so platform operators can set a sensible
default without requiring every agent to configure one explicitly:
request_input(retry_policy=...) ← call-site (highest priority)
→ BaseAgent.default_human_retry_policy ← agent class default
→ server suspension.default_retry_policy ← platform default (lowest)
UpstreamIntentSuspendedError
from openintent import UpstreamIntentSuspendedError
try:
spec.validate_claim_inputs(task_id, completed_outputs)
except UpstreamIntentSuspendedError as e:
print(e.task_id) # the claiming task
print(e.phase_name) # the upstream phase that is suspended
print(e.suspended_intent_id)
print(e.expected_resume_at) # ISO 8601, may be NoneRaised by WorkflowSpec.validate_claim_inputs() when a declared input references an
upstream phase whose intent is currently suspended_awaiting_input. Subclass of
WorkflowError.
New EventType Constants
| Constant | Fired when |
|---|---|
EventType.SUSPENSION_RENOTIFIED |
Each re-notification attempt fires |
EventType.SUSPENSION_ESCALATED |
An escalation ladder step fires |
EventType.PORTFOLIO_MEMBER_SUSPENDED |
A portfolio member intent suspends |
EventType.PORTFOLIO_MEMBER_RESUMED |
A portfolio member intent resumes |
retry_policy on SuspensionRecord
SuspensionRecord gains an optional retry_policy: HumanRetryPolicy | None field.
Existing single-attempt behaviour is fully preserved when the field is absent.
timeout_seconds is now documented as a per-attempt window when retry_policy is set.
New Exports
from openintent import (
HumanRetryPolicy,
EscalationStep,
UpstreamIntentSuspendedError,
)Cross-RFC Patches
| RFC | Change |
|---|---|
| RFC-0002 | suspended_awaiting_input counter in aggregate status; completion-gate clarification |
| RFC-0007 | Portfolio suspension-aware aggregate fields; member_suspended / member_resumed events |
| RFC-0010 | Relationship note — RFC-0010 retries on agent failure; RFC-0026 re-notifies on human non-response |
| RFC-0012 | Task/intent suspension mirror; suspended_tasks in plan progress |
| RFC-0024 | UpstreamIntentSuspendedError at claim time; suspended_phases in workflow progress |
| RFC-0025 | retry_policy on SuspensionRecord; per-attempt timeout_seconds semantics; fallback_policy alias; extended cross-RFC table |
What's Not Changed
- Existing single-attempt
request_input()calls require no changes. - Agents that don't set
retry_policybehave exactly as before. suspended_awaiting_inputstatus is still intent-local — it is not the same as
completed, and dependents remain blocked (not failed) until the intent resumes.
Testing
- 41 new tests in
test_hitl.pyandtest_workflow_io.py - 1052+ tests across 19 test files — all passing
ruff checkclean (80 files, 0 issues)mkdocs build --strictpasses
Installation
pip install openintent==0.17.0Or with server extras:
pip install "openintent[server]==0.17.0"Full Changelog
See CHANGELOG.md for the complete change log.
v0.16.0
OpenIntent SDK v0.16.0
Released: 2026-03-23
This release ships two new protocol RFCs — typed workflow I/O contracts (RFC-0024) and human-in-the-loop intent suspension (RFC-0025) — plus a fix that hardens the OpenAI adapter against the max_tokens deprecation in gpt-5+ and o-series models. All changes are fully backward compatible.
What's new
RFC-0024: Workflow I/O Contracts
Agents no longer need to agree on data formats at runtime. Declare what each phase produces and consumes in YAML; the executor handles all wiring automatically.
Output schemas — declare what a phase produces:
workflow:
analyze:
title: Analyze document
assign: analyst-agent
outputs:
summary: string
confidence: number
decision:
type: ApprovalDecision
required: falseInput wiring — map local names to upstream phase outputs, trigger payload, or initial state:
review:
title: Human review
assign: review-agent
depends_on: [analyze]
inputs:
doc_summary: analyze.summary
trigger_owner: $trigger.owner
outputs:
approved: booleanParse-time validation — broken wiring is caught at startup (from_yaml()), not at runtime.
Three executor gates:
resolve_task_inputs()— pre-populatesctx.inputbefore the agent runsvalidate_claim_inputs()— rejects a claim early if upstream outputs aren't readyvalidate_task_outputs()— validates the agent's return dict against declared types
Named error types (all exported from openintent):
from openintent import (
MissingOutputError, # required key absent from return value
OutputTypeMismatchError, # value doesn't match declared type
UnresolvableInputError, # input ref can't be resolved
InputWiringError, # structural error at parse time
)Named types — define reusable struct and enum types in a top-level types: block:
types:
ApprovalDecision:
enum: [approved, rejected, needs_review]
DocumentSummary:
fields: [title, body, word_count]Incremental adoption: phases without outputs or inputs are fully unaffected.
RFC-0025: Human-in-the-Loop Intent Suspension
Agents can now pause mid-execution, present a structured question to an operator, and resume after a response arrives.
Suspend and wait for input:
decision = await self.request_input(
question="Refund amount exceeds policy limit. Approve?",
response_type=ResponseType.CONFIRM,
confidence=0.45,
timeout_seconds=3600,
fallback_policy="reject",
)
if decision == "yes":
await self.approve_refund(intent)Structured choices:
decision = await self.request_input(
question="How should we handle this duplicate order?",
response_type=ResponseType.CHOICE,
choices=[
SuspensionChoice(value="cancel_new", label="Cancel new order", style="danger"),
SuspensionChoice(value="cancel_old", label="Cancel original order"),
SuspensionChoice(value="keep_both", label="Keep both orders", style="primary"),
],
)Engagement decision engine:
signals = EngagementSignals(confidence=0.4, risk=0.8, reversibility=0.9)
decision = await self.should_request_input(signals)
# decision.mode → "require_input"
# decision.rationale → "Low confidence and high risk require operator approval"Lifecycle decorators:
@on_input_requested
async def notify_slack(self, suspension: SuspensionRecord):
await slack.post(channel="#ops", text=suspension.question)
@on_input_received
async def log_response(self, response: InputResponse):
await audit_log.record(response)
@on_suspension_expired
async def apply_fallback(self, suspension: SuspensionRecord):
await metrics.increment("suspension.expired")
@on_engagement_decision
async def audit_decision(self, decision: EngagementDecision):
await audit_log.record(decision)Operator REST API:
POST /api/v1/intents/{id}/suspend/respond
{
"suspension_id": "susp_abc123",
"value": "yes",
"responded_by": "operator@example.com"
}Returns choice_label, choice_description, and the updated intent state. Returns 422 with valid_choices if the value is not among the declared options.
Fallback policies — "reject", "approve", "fail", "escalate" — control what happens if the suspension window expires with no response.
Bug fixes
OpenAI max_tokens → max_completion_tokens for gpt-5+ and o-series models
OpenAI deprecated the max_tokens parameter for newer model families, causing 400 errors with gpt-5-mini, o1, o3, and similar models. This release fixes it in two places:
-
OpenAIAdapter— automatically remapsmax_tokenstomax_completion_tokensfor any model matchinggpt-5*,o1*, oro3*. Existing callers passingmax_tokensget correct behaviour transparently; callers already usingmax_completion_tokensare unaffected. Older models (gpt-4,gpt-3.5-turbo, etc.) are unchanged. -
trydemo script — bothResearchAgentandSummarizerAgentnow passmax_completion_tokensdirectly in all call paths (streaming and non-streaming).
Demo script model name — corrected gpt-5.2-mini to gpt-5-mini.
Upgrade guide
This release is fully backward compatible. No changes are required to existing code.
To adopt RFC-0024 I/O contracts on a phase, add outputs: and/or inputs: keys to that phase's YAML config. All other phases are unaffected.
To adopt RFC-0025 HITL, call await self.request_input(...) anywhere inside an agent run() method. Install the new decorators as needed.
If you were working around the max_tokens 400 error by passing max_completion_tokens directly, you can continue doing so — it takes precedence and nothing changes. If you were passing max_tokens, the adapter now handles the translation for you.
Install:
pip install openintent==0.16.0MCP server:
npm install @openintentai/mcp-server@0.16.0Full changelog
See CHANGELOG.md for the complete list of changes.
Stats
- 25 RFCs implemented
- 228 tests passing (93 new for RFC-0024 · 110 for RFC-0025 · 7 new adapter tests · 18 existing)
ruff check/ruff formatcleantsc --noEmitclean
v0.15.1
v0.15.1 — Gemini Adapter Rebuild for google-genai SDK
Changed
-
Gemini SDK Migration — Replaced deprecated
google-generativeaiSDK withgoogle-genai(v1.0+). TheGeminiAdapternow uses the moderngenai.Clientpattern (client.models.generate_content/client.models.generate_content_stream) instead of the legacygenai.configure()+GenerativeModel()approach. -
GeminiAdapter Rewrite — Full protocol parity with OpenAI/Anthropic adapters:
- Prompt/completion/total token counts from
usage_metadata - Finish reason mapping from candidates
- Function call tracking with provider-native IDs
- Streaming usage metadata from final chunks
- Multi-turn
GeminiChatSessionwith proper history management (including during streaming)
- Prompt/completion/total token counts from
-
LLMEngine Gemini Integration — Added
_messages_to_gemini_contents()for proper message conversion (system messages becomesystem_instruction, assistant messages usemodelrole),_tools_to_gemini_format()for tool schema conversion to Gemini function declarations, and raw provider fallback paths for Gemini in both_call_raw_providerand_stream_raw_provider. -
Default model names updated from
gemini-1.5-pro/gemini-2.0-flashtogemini-3-flashacross SDK, docs, and frontend. -
Dependency —
google-generativeai>=0.4.0replaced withgoogle-genai>=1.0.0ingeminiandall-adaptersoptional extras.
Updated
- All version references updated to 0.15.1 across Python SDK, MCP server package, documentation, and changelog.
- Documentation and examples updated to reflect new SDK patterns and model names.
Install
pip install openintent[gemini]==0.15.10.15.0
v0.15.0 — Native FastAPI SSE & RFC-0010 Retry MCP Tools
Highlights
RFC-0010 Retry Policy MCP Tools — The protocol server already had retry policy endpoints, and the Python SDK already had client methods, but neither MCP implementation exposed them. This release closes that gap with 4 new tools in both the TypeScript MCP server and the Python MCP bridge:
| Tool | Tier | Description |
|---|---|---|
openintent_set_retry_policy |
admin | Configure retry policy (strategy, max retries, backoff, fallback agent) |
openintent_get_retry_policy |
read | Retrieve current retry policy |
openintent_record_failure |
write | Record a failure with attempt number, error code, and scheduled retry |
openintent_get_failures |
read | Query failure history |
MCP tool surface: 66 → 70 tools. RBAC counts: reader=25, operator=43, admin=70.
Native FastAPI SSE — Replaced sse-starlette with FastAPI's built-in SSE support (EventSourceResponse + ServerSentEvent). One fewer dependency, cleaner streaming, spec-compliant keep-alive pings.
What's New
Added
- 4 RFC-0010 MCP tools in TypeScript MCP server (
tools.ts,client.ts,security.ts) build_retry_failure_tools()in Python MCP bridge (openintent.mcp)- MCP tool access documentation in cost-retry guide
Changed
- SSE endpoints migrated to native FastAPI (
fastapi>=0.135.0) - All version references updated to 0.15.0
Removed
sse-starlettedependency
Install
pip install openintent==0.15.0v0.14.1
[0.14.1] - 2026-02-27
Fixed
-
SDK/Server field format mismatches — Fixed three categories of mismatches between the Python SDK client and the protocol server's Pydantic models:
constraintstype mismatch —create_intent(),create_child_intent(), andIntentSpecsentconstraintsas alist[str](e.g.,["rule1", "rule2"]), but the server expectsDict[str, Any](e.g.,{"rules": [...]}). All three methods (sync and async) now accept and senddict[str, Any].Intent.from_dict()retains backward compatibility for legacy list-format constraints.createdBy→created_byfor portfolios —create_portfolio()sentcreatedByandgovernancePolicy(camelCase) but the server'sPortfolioCreatemodel expectscreated_byandgovernance_policy(snake_case). Fixed in both sync and async clients.get_portfolio_intents()response parsing — The server returns a raw JSON array fromGET /api/v1/portfolios/{id}/intents, but the SDK expected a{"intents": [...]}wrapper dict, silently returning an empty list.
-
Silent empty results from list endpoints — Seven additional list-returning methods used
data.get("key", [])which silently returned empty lists when the server sent raw JSON arrays. All now useisinstance(data, list)detection to handle both raw array and wrapped dict responses:list_portfolios()— expected{"portfolios": [...]}get_intent_portfolios()— expected{"portfolios": [...]}get_attachments()— expected{"attachments": [...]}get_costs()— expected{"costs": [], "summary": {}}get_failures()— expected{"failures": [...]}get_subscriptions()— expected{"subscriptions": [...]}federation_list_agents()— expected{"agents": [...]}
-
IntentLease.from_dict()KeyError on server responses —acquire_lease()threwKeyError('status')because the server'sLeaseResponsemodel does not include astatusfield (it usesacquired_at,expires_at, andreleased_atto represent lease state).IntentLease.from_dict()now derives status from these fields:RELEASEDifreleased_atis set,EXPIREDifexpires_atis in the past, otherwiseACTIVE. Also handles the field name differenceacquired_at(server) vscreated_at(SDK). Backward compatible with the SDK's own serialization format. -
Stale database singleton after server restart —
get_database()cached theDatabaseinstance at module level and never checked whetherdatabase_urlchanged between calls. When the protocol server restarted on a different port (e.g.,openintent_server_8001.db→openintent_server_8002.db), the singleton kept pointing at the old file. Writes went to the old database; reads came from the new (empty) one — intents appeared created but were invisible tolist_intents. The singleton now tracks its URL and recreates the connection when the URL changes. -
Example and test updates — All examples (
basic_usage.py,openai_multi_agent.py,multi_agent/coordinator.py,compliance_review/coordinator.py) and tests updated to use dict-format constraints.
Changed
- All version references updated to 0.14.1 across Python SDK, MCP server package, and changelog.
v0.14.0
v0.14.0 — Federation Protocol & Security
Adds RFC-0022 (Federation Protocol) and RFC-0023 (Federation Security), providing cross-server agent coordination with cryptographic identity, signed envelopes, UCAN delegation tokens, and trust policy enforcement. Includes a complete Python SDK implementation, Express.js endpoints, MCP tools, and documentation.
Protocol Specifications
- RFC-0022: Federation Protocol — Federation contract for cross-server agent coordination: envelope format, agent visibility (public/unlisted/private), peer relationships (peer/upstream/downstream), callbacks with at-least-once delivery, intent authority model, delegation scope with UCAN-style attenuation, governance propagation (strictest-wins), federation attestation (OpenTelemetry conventions), discovery via
/.well-known/openintent-federation.json, and federation-aware leasing. - RFC-0023: Federation Security — Authentication, authorization, and verification layer: server identity via
did:web, signed envelopes (HTTP Message Signatures, RFC 9421), UCAN delegation tokens with attenuation and expiry, trust policies (open/allowlist/trustless), agent access policies, signed attestations, and cross-server event log reconciliation via RFC-0019 Merkle primitives.
Python SDK — 5-Layer Federation Implementation
| Layer | Module | Contents |
|---|---|---|
| Models | openintent/federation/models.py |
FederationEnvelope, FederationCallback, FederationPolicy, FederationAttestation, DelegationScope, FederationManifest, FederationStatus, DispatchResult, ReceiveResult, FederatedAgent, PeerInfo. Enums: AgentVisibility, PeerRelationship, TrustPolicy, CallbackEventType, DispatchStatus. |
| Client | openintent/client.py |
federation_status(), list_federated_agents(), federation_dispatch(), federation_receive(), send_federation_callback(), federation_discover() — sync and async variants. |
| Server | openintent/server/federation.py |
FastAPI router: GET /status, GET /agents, POST /dispatch, POST /receive, GET /.well-known/openintent-federation.json, GET /.well-known/did.json. SSRF validation, callback delivery with retry, governance enforcement, idempotency keys. |
| Security | openintent/federation/security.py |
ServerIdentity (Ed25519, did:web), sign_envelope()/verify_envelope_signature(), MessageSignature (RFC 9421), TrustEnforcer (open/allowlist/trustless), UCANToken (create/encode/decode/attenuate), resolve_did_web(), validate_ssrf(). |
| Decorators | openintent/federation/decorators.py |
@Federation (class decorator), federation_visibility on @Agent, federation_policy on @Coordinator, lifecycle hooks: @on_federation_received, @on_federation_callback, @on_budget_warning. |
Express.js Server
- 4 REST endpoints:
GET /api/v1/federation/status,GET /api/v1/federation/agents,POST /api/v1/federation/dispatch,POST /api/v1/federation/receive - Federation audit trail: dispatch IDs, provenance in
state._federation, RFC-0020 trace propagation origin_server_urlfield onagent_recordstable for federated agents
MCP Tools
- 4 new tools:
federation_status(read),list_federated_agents(read),federation_dispatch(admin),federation_receive(admin) - Tool surface: 62 → 66 tools. RBAC counts: reader 23, operator 40, admin 66.
Federation Event Types
FEDERATION_DISPATCHED, FEDERATION_RECEIVED, FEDERATION_CALLBACK, FEDERATION_BUDGET_WARNING, FEDERATION_COMPLETED, FEDERATION_FAILED
Key Algorithms
DelegationScope.attenuate()— Scope narrowing per hop: intersection of permissions, union of denied operations, minimum delegation depth.FederationPolicy.compose_strictest()— Strictest-wins governance: minimum for numerics, OR for booleans, merge for observability.
Documentation
- Federation sections added to all 5 website pages: Docs, API Reference, Agents, Examples, Adapters.
- MkDocs site rebuilt with federation content:
guide/federation.md— Concepts, configuration, code examplesexamples/federation.md— Runnable examples for dispatch, signing, UCAN, trust enforcementapi/federation.md— Complete class and method referencerfcs/0022-federation-protocol.md— Full RFC specificationrfcs/0023-federation-security.md— Full RFC specification
- Homepage updated: 23 RFCs, 800+ tests, v0.14.0, federation feature cards.
Discovery & Compatibility
/.well-known/openintent.json—federationcapability added, RFC-0022/0023 inrfcUrls/.well-known/openintent-compat.json— RFC-0022 (full), RFC-0023 (partial)/.well-known/openintent-federation.json— New federation discovery endpoint/.well-known/did.json— DID document for server identity
Tests
82 new federation tests covering:
- Model serialization round-trips
- Security: sign/verify, UCAN create/encode/decode/attenuate, SSRF blocking, trust enforcement
- Server endpoints via TestClient + SQLite
- Decorator configuration and lifecycle hooks
- Integration flows (dispatch → receive → callback)
Breaking Changes
None. Federation is additive — existing APIs and behavior are unchanged. Federation operates in trusted mode by default; RFC-0023 security is opt-in.
v0.13.5
v0.13.5 — MCP Governance Tool Surface Complete
Date: 2026-02-14
What's New in v0.13.5
MCP Governance Enforcement Tools
The MCP server now exposes the complete 62-tool surface with all 4 governance enforcement tools fully implemented end-to-end:
| Tool | Tier | Description |
|---|---|---|
set_governance_policy |
admin | Set or update governance policy on an intent (uses If-Match for optimistic concurrency) |
get_governance_policy |
reader | Retrieve the effective governance policy for an intent |
approve_approval |
admin | Approve a pending approval gate created by request_approval |
deny_approval |
admin | Deny a pending approval gate with optional reason |
Each tool has the full implementation chain: tool definition, input schema, client method, handler case, and RBAC tier assignment.
Bug Fixes
- MCP Startup Tool Count — Fixed a mismatch where the RBAC security tier definitions listed 62 tools but only 58 tool definitions existed in
tools.ts. The MCP server startup log now correctly reportstools=62/62for admin role. - RBAC Operator Count — Corrected the
operatorrole count from 37 to 38 across all documentation and changelog entries.
Version Notes
- v0.13.3 and v0.13.4 were npm publish patch releases for the
@openintentai/mcp-serverpackage (GitHub Actions OIDC configuration and provenance fixes). - v0.13.5 is the first release where the MCP TypeScript implementation fully matches the protocol specification for all 21 RFCs.
RBAC Tool Counts
| Role | Tools | Description |
|---|---|---|
reader |
21 | Read-only tools (default role) |
operator |
38 | Read + write tools |
admin |
62 | Full access including governance, lifecycle, and identity tools |
Version Matrix
| Component | Version |
|---|---|
Python SDK (openintent) |
0.13.5 |
MCP Server (@openintentai/mcp-server) |
0.13.5 |
Upgrade Guide
# Python SDK
pip install openintent==0.13.5
# MCP Server
npm install @openintentai/mcp-server@0.13.5
# Or run directly
npx @openintentai/mcp-server@0.13.5MCP Server Usage
# Start with admin role (all 62 tools)
OPENINTENT_MCP_ROLE=admin npx @openintentai/mcp-server
# Start with operator role (38 tools)
OPENINTENT_MCP_ROLE=operator npx @openintentai/mcp-server
# YAML workflow shorthand
tools:
- "mcp://npx/-y/@openintentai/mcp-server?role=admin"Full Changelog
See CHANGELOG.md for the complete history.
v0.13.4
Fixes for mcp-server publishing.
v0.13.3
Publishing mcp-server to npm.
v0.13.2
v0.13.2 — npm Scope Rename + Codex & Streaming Fixes
Date: 2026-02-14
What's New in v0.13.2
npm Package Scope Rename
The MCP server TypeScript package has been renamed from @openintent/mcp-server to @openintentai/mcp-server to match the secured npm organization.
Update your install commands:
npm install @openintentai/mcp-server
# or
npx @openintentai/mcp-serverUpdate mcp:// URIs in YAML workflows:
tools:
- "mcp://npx/-y/@openintentai/mcp-server?role=operator"All documentation, examples, YAML workflows, Makefile targets, and website pages updated accordingly.
OpenAI Codex Model Support (from v0.13.1)
Automatic routing for codex-family models (gpt-5.2-codex, o3-codex, etc.) that use the /v1/completions endpoint instead of /v1/chat/completions.
- New
codex_utilsmodule withis_codex_model(),messages_to_prompt(), andchat_kwargs_to_completions_kwargs()helpers OpenAICompletionswrapper class normalizes completions-API responses to the standard content interface- LLM engine routing updated in
_call_llm,_stream_llm, and raw provider paths to auto-detect and redirect codex models
Anthropic Streaming Usage Fix (from v0.13.1)
Fixed two bugs causing token usage data to be silently lost during streaming:
- Wrapped event consumption loop in
try/finallyso usage is saved even when the stream consumer exits early (GeneratorExit) - Added
_resolve_usage()fallback that callsget_final_message()when event parsing misses usage data, ensuring accurate cost tracking for all Anthropic models including those with extended thinking
Version Matrix
| Component | Version |
|---|---|
Python SDK (openintent) |
0.13.2 |
MCP Server (@openintentai/mcp-server) |
0.13.2 |
Upgrade Guide
# Python SDK
pip install openintent==0.13.2
# MCP Server
npm install @openintentai/mcp-server@0.13.2If upgrading from v0.13.0 or earlier, update any @openintent/mcp-server references to @openintentai/mcp-server in your config files and YAML workflows.