Repository navigation
lionagi v0.37.0
Minor release with breaking changes, listed under "Breaking changes" with what a caller has to change for each: the MCP server no longer accepts its flat operation names such as submit_agent, and several registration, configuration, import and gate paths now refuse input they used to accept. The headline changes are the move of provider integrations and LNDL to a lionhub import root in the same distribution, with the old paths working until 2.0.0, and a hosted Studio page paired by li studio that keeps its access across reloads, tabs and bookmarks until the daemon restarts.
Breaking changes
From griffe 1.15.0 (find_breaking_changes against the v0.36.0 package) and the changelog's Removed and Changed entries, which cover the wire answers, refusals and environment handling griffe cannot see. griffe also reports items that need no caller change: the eight package paths that moved to lionhub (each still imports until 2.0.0), the LNDL names the top-level package now exports lazily, message to_dict overrides that are now inherited, deprecated arguments whose defaults became None, state-schema and tool-description constants, a state lifecycle method callers do not call, and a new dataclass field that shifts later positional arguments of AgentSpec (seatbelt before khive_injection, #3779); construction by keyword is unchanged.
- MCP flat operation names. Inside
ops, the MCP server refuses the flat names of its earlier surface (submit_agent,submit_flow,submit_fanout,submit_play,job_status,job_output,job_kill,job_wait,jobs_list,server_info) withnot_found. Use the namespaced verb instead, such asagent.submitorjob.list. The catalog andserver.infoalso drop theirsynonyms_removed_afterfield. (#3847) _import_all_providers()removed. The private helper and its module list are gone fromlionagi.service.connections.registry. Add a new built-in provider as a row in the hub's provider manifest instead. (#4108)- Session observer gates. A
SessionObservergate must return aboolor aGateResult. Other values, such as1or"yes", now deny routing and subscriber delivery, though the event is still recorded. (#4001) - MCP registration by server name. With an explicit config file, a missing server name is refused before any tool is registered. A name absent from the default configuration raises the loader's "not declared in the selected config" error, and a missing default
.mcp.jsonraisesFileNotFoundError. Declare the server in the config you select, or provide the default file. Inline transport values must be exact built-inNone,bool,int,float,str,list,tupleordictvalues;Path, subclasses and cyclic structures raiseValueError. (#3918) - Coding commands drop credential variables. Bash, search, check, AST search, sandbox Git, engine gates, repairs and the formatter hook remove declared credential names, sensitive-name patterns,
BASH_ENVandENVfrom their child environments,GITHUB_TOKENincluded. Patterns match anywhere in a name, soDATABASE_URLgoes too. Restore a variable by its exact spelling incommand_env_allowlist. (#3848) - Unreadable coding settings. If
~/.lionagi/settings.yamlcannot be read, or itssecrets.lookupsection is invalid, building a coding agent, a toolkit orBashToolraisesConfigurationError. Fix or remove the file or the section. (#3848) - Loader import errors. Application and provider module loaders raise a plain
ImportErrorthat names the module path. The original error is kept only as__cause__, so the outer.nameand.pathareNone. A missing-module error is re-raised unchanged. (#3790) run_synckeywords.lionagi.ln.concurrency.run_syncreservesabandon_on_cancelandlimiteras offload controls, and rejects a non-booleanabandon_on_cancel. For a callable that takes either keyword, bind its arguments withfunctools.partialand pass that callable. (#3733, #3785)- Empty replies get no reformat request.
parse(), andoperate()andReAct()through it, no longer send up to four reformat requests for a reply with no text, and return thehandle_validationoutcome at once. To keep the retries, call the method again on that outcome: theExtractionErrorunder"raise", or theUnparsedResponseof kindextractionunder"return_value". (#3763) - Bash
timeout=0. An explicittimeout=0inCodingToolkit's bash tool now clamps to 1 ms. It used to mean the 30-second default. Leavetimeoutunset for the default, or pass a real limit. (#3861) - Context-window lookup raises. If the provider hub is missing or fails to load, lookup raises
MissingFeatureError,ProviderActivationErroror, for an unsupported manifest version,ProviderContractVersionError. It used to return the 128,000-token estimate. (#4097) load_mcp_toolswithoutserver_names. Withconfig_path=..., only the servers that file declares are registered. Passserver_namesto choose servers explicitly. (#3845)AccountRoutingErrorfields. Settingprovider_error_typeorrejection_classwith any code other thanrequest_rejectednow raisesValueError. (#4123)- Moved private helpers and patch targets. Helpers moved out of
lionagi.cli.mirror,lionagi.studio.cliandlionagi.cli.killintolionagi.cli._mirror_service,lionagi.cli._schedule_parsingandlionagi.cli._kill_service, and kill helpers used outside that module lost their leading underscore. Patchlionagi.protocols.action.gateorlionagi._settingsinstead of thelionagi.agentmodules. Patchinglionagi.cli._logging.warnno longer reaches core code, which useslionagi._log_channels. (#3768, #3771, #4039, #4045, #4069)
Deprecations
- Session gate filtering. Filtering emitted events through a Session gate is deprecated. Use route predicates or subscribers for observations, and
authorizefor decisions. No removal release is named. (#4018) - Session and toolkit arguments.
Session.remove_branch(delete=...),exclude_cloneandexclude_loadonSession.to_df()andSession.concat_messages(), andCodingToolkit(notify_threshold=..., notify_max_tokens=...)now emit aDeprecationWarningwhen passed. All will be removed in a future minor release. (#3850, #3861) - Provider helpers moved into the core.
lionagi.providers._provider_errors,_secret_resolution,_subagent_admissionandopenai._chat_schemasnow live atlionagi._provider_errors,lionagi.service.accounts._secret_resolution,lionagi.service._subagent_admissionandlionagi.service.connections._chat_schemas. The old paths work until 2.0.0 and warn once. (#4073, #4076, #4077) - Packages moved to
lionhub.lionagi.providers,lionagi.lndl,lionagi.orchestration,lionagi.engines,lionagi.dispatch,lionagi.work,lionagi.mcpandlionagi.operations.lndl_middlenow live underlionhub, for examplelionhub.providersandlionhub.lndl.middle.lionhubships in the same distribution, so installs need nothing new. Each old path works until 2.0.0, returns the same module object and emits oneDeprecationWarningnaming the new path. The nine root exports, such aslionagi.LNDLOutput, warn on first use.lionagi._moved.MOVEDlists every move. (#3752, #3753, #3754, #3769, #4077, #4079)
Behaviour changes
- State store schema 6. The store moves to schema version 6, which records terminal-delivery eligibility and consumer registrations. Restart every process that opens the store after upgrading, including Studio daemons, schedulers and CLI processes already running, because an old process can write rows that replay excludes. The first open classifies every existing transition in one transaction. On PostgreSQL that locks
status_transitionsuntil it commits, and on SQLite it takes the single write lock, so writers wait for a time that grows with the table. (#3914) - Moved modules report new paths. Moved modules report the
lionhubpath in__name__,__module__,__file__and tracebacks, and a static type checker finds no module at an old path. None of this comes with a warning. (#3752) - User-wide
.env. Settings also read.envunderLIONAGI_HOME(~/.lionagi/.envby default). It ranks below the working directory's.env,.env.localand.secrets.env, and below the environment. A value there, such asLIONAGI_STATE_DB_URLor a provider key, reaches every lionagi process of that user. (#3783) - Anthropic output limit in
li agent. An Anthropic API-modelli agentrun whose model names no output limit sendsmax_tokens=32768, thinking included. It used to send 8,192. (#3763) - Restored API models. A restored API model without a stored request schema validates and coerces requests against the registered one. A payload that passed unvalidated may now be refused. (#4014)
- Sync
add_messagehooks.is_coro_funcnow recognizes callable instances with an async__call__, and synchronousadd_message()rejects them. Usea_add_message()for those hooks. (#3906) - Provider refusals. A turn the provider refuses is recorded as
run.failed.provider_nonretryable, notrun.failed.exception. ItsFailedRoundErrorcarriesstop_reasonand the provider's refusal detail. (#4040, #4065) - Cut-off replies. An API-model
li agentrun whose reply is cut off at the output limit, does not parse, or has no text is continued at most twice, then fails withFailedRoundError. It used to end as completed with the work undone. (#3763) - MCP config files. A server set read from
--mcp-configis the agent's whole set on every launch path. The Claude CLI gets--strict-mcp-config, and the Codex CLI disables the servers its own configuration declares. Existing agents keep their built selection, so rebuild them to get launch-time enforcement. (#4012, #4053) - Run records.
run.jsonno longer recordsLIONAGI_API_ACCOUNTasapi_accountfor a run that routes through the account router. The paying account is inapi_usage. (#4096) - Session gates. A session tool gate sees arguments bound to the callable's signature, with defaults applied, when binding succeeds. A gate denial stores a redacted
GateDeniedsignal, and the proposed action is no longer kept in the denial's Flow copy. (#4001, #4018) - ReviewEngine prompt caching. With
prompt_caching=True, the artifact goes in one turn before the dimension reviewers, and all dimensions share one system prompt. A failed artifact turn is reported asartifact_turn_failedorartifact_turn_unused. (#3915) - Endpoint lookup.
EndpointRegistry.matchwith no endpoint named resolves a catalog-declared provider to its default endpoint, whatever was imported first.list_providers()listscodexafter the OpenAI endpoints instead of second. (#4104, #4108) - Linux
li kill. On Linux,li killkeeps a live run whose start time or boot time disagrees between readers. A live process with a disagreeing recorded start time is held as unknown rather than swept. (#3955)
Studio
- Hosted page pairing. A hosted Studio page paired by
li studiokeeps the daemon's launch bearer inlocalStorage, bound to the daemon's API base. It forgets the bearer on the first 401 that carried it, so a restarted daemon asks forli studioagain. (#4116) - Pairing response.
POST /api/studio/pairreturnstoken_source, which is"launch"for the daemon's per-start launch bearer or"configured"whenLIONAGI_STUDIO_AUTH_TOKENis set. (#4116) - Loopback and port checks.
li studio, theli scheduleclients and theli doctordaemon check reach a daemon onlocalhost,127.0.0.0/8or::1without a configured proxy.li studioalso checks that it can bind its port before it prints a pairing link. (#4117) - Terminal reconciliation (opt-in). With
LIONAGI_STUDIO_TERMINAL_RECONCILEset on (off by default), Studio reconciles eligible terminal transitions for a registered settings consumer at startup and on each periodic tick. Delivery is at least once. With the setting on, a transition whose push already ran the notifier is replayed, so a shell command notifier runs twice, while a Python hook can deduplicate by transition event ID. (#3914) - SQLite session pages. Recent session pages on SQLite skip newer hidden engine transcripts when a compatible optional index is available. Building that index on open holds the SQLite write lock until it finishes. (#4025)
- Session pages and live streams. Unfiltered pages use the timestamp index, and single-branch statistics reuse captured JSON (#3910); snapshot-based live streams are shared (#3812).
- Operator. Bounded cleanup after a failed or cancelled setup (#4017); turns finish after run teardown (#3951).
- Notification delivery. Independent outcomes, consumer inspection, durable attempts and settings, late outcomes, and async-delivery capacity (#3966, #3967, #3968, #3969, #3989, #3960).
Agents and li agent
- Output limits.
AgentSpec.max_tokens,Engine(max_tokens=...)andReviewEngine(stage_max_tokens={...})set the Anthropic output limit per agent or review stage. (#3865) - Context folding. API chat and
operatefold earlier tool records under a per-request input ceiling. (#3732) - Bounds and folds. Per-run API result bounds and fold settings (#3755); context index built once per call (#3759); API-model output limit, continuation and result bounds (#3787).
- Run records. Provider, model, prompt size and cap decisions in
run.json.api_usage(#3726); worker spawns recorded before output (#3863); launcher account name recorded (#3879). - LNDL calls.
lndl-callsloops show tools only as calls (#3801); known reads declared per turn, up to 16 (#3806). - Runs, launch and profiles.
no_delivery_commandfailure (#4047); resume-race guard for cancellation (#3928); restored system prompt (#4031); teardown keeps cancellation (#3862); fold margin is a launch setting (#3895); frontmatter examples do not warn (#3738).
Engines, tools and hooks
- Structured replies. A cut-off
communicate()fails without a repair request (#4094); fenced JSON inside JSON (#3763); batch calls decode once (#3850). - ReAct. Cut-off text no longer ends the turn on an input-cap error (#4094); no display setting in API requests (#4014); repairs replace invalid history (#4021).
- Judges and emission. Only a whole
PASStoken passes (#3743); denial survives notification errors (#3908); refusals propagate (#4061); failed reply recorded (#3829), text kept off unless asked (#3838); list emissions read per element (#4105). - Reviews. Verdict synthesis marked as the final request (#3891); clean-verdict audit (#4106).
- Tools. Unnamed call answered (#3788); denied call reaches post hooks (#3739); bash runs in workspace root (#3821); reader extent and stream reaping (#3843); deep arguments still run (#4024); over-deep output placeholder (#4067);
LionTooland flow request contracts move to core (#3770, #3774). - LNDL. No tool schema without call-rendered tools (#3805); reserved words kept in strings (#3904).
Providers and accounts
- Prompt caching.
prompt_cachingonAgentSpecandEngineplaces marks from earlier entries (#3811, #3866); cache read and write counts per request (#3926). - Cache placement. OpenAI stable prefix (#3920);
cache_intentexported (#3886); no end-of-turn mark ahead of a fold (#3888); context blocks kept at their turn (#3864, #4057). - Pricing. Responses reporting standard speed are priced again (#3758, #3761, #3786).
- Credential ledger. Warm-prefix routing (#4044); month follows credit refresh (#3802); key refusal names its account (#3900); no hang on a saturated thread pool (#4046).
- Rejections. Provider error type and rejection class recorded (#4120); an unclassified body logs one debug record (#4123).
- Catalog. Declarations and composition (#4089); manifest without endpoint imports (#4092); discovery error types (#4086);
_configcontext tables (#4090);provider_catalogon match andiModel(#4113); lookup and ordering (#4097). - Models and imports. Context window on every route (#4103); model context-window and effort-ceiling entry (#3892); declared reasoning effort (#3923);
lionagi.providers.errorsexceptions (#3948); root logger untouched (#4023); whitespace-only history skipped (#3815).
MCP server
- Stdio handshake. Servers that close their pipe on a first non-
initializerequest reconnect under FastMCP 4 after a legacy retry;"handshake": "legacy"skips the first try. Stdio handshake pinned (#3794, #3795, #3804). - Exclusive selections. Honored in CLI agents (#4002); carried through request serialization (#4012).
- Jobs and config. Job processes reaped on exit (#4087); configuration snapshot ownership (#4019).
Schedules
- Merged pull-request scans. An incomplete poll defers merged pull requests until a complete scan establishes merge order (#3749); schedules persist a page limit from 5 to 100, and scans send no conditional requests (#3927).
- Polling. Overdue after three settled capped polls (#3740);
gh auth tokenexchange times out (#4063). - Validation. Declarations validate without importing the schedules router (#4056); chains validated at create and update (#4058); parsing module owns the depth cap (#4052).
Command line and li kill
- Kill. Recorded workers of terminal and dead-runner sessions stopped (#3899); group termination retried (#3941); teardown bounded (#3973); deadline message (#3958); imported run checked before reaping (#4075).
- Signals and identity. CLI child signalled despite a group error (#3885); boot-time group kill kept (#3820); identity read until exec (#3901); group absence read after reaping (#3868).
- Monitor and team. Monitor fails on an unreadable store (#3903); single-name recipients (#3852).
- Helpers.
current_pid_markersmoves tolionagi.ln._proc, re-exported by kill (#4049).
State store
- Writes. Failed SQLite workers drained (#3767); retained references kept on prune (#3934); progression IDs validated (#3944); unsupported checkpoint versions refused (#3953); checkpoint v3 primitives (#3970); worker spawns recorded (#3854).
- Run imports. Conflicting shared messages refused (#3986); shared messages kept and incomplete runs rolled back (#4055).
Security
- Write profiles on macOS.
api_tools: writeruns bash and editor under a Seatbelt policy, with the network off unlessapi_network: true. (#3779) - Email headers. Secure coding agents refuse email addresses in outbound HTTP headers, bash commands and editor writes. (#4015)
- Redaction. Signing-key field names masked across spellings (#3905); adapter error strings (#4016); failure logs (#3974); linear-time email guard (#4022); provider-key-prefixed account names refused (#3883).
- Keys in child processes. Routed keys kept out of CLI children (#3791, #3792); missing credential refused at dispatch (#3818); non-secret references rejected (#3824).
- Secret lookup and refusals. Bounded cleanup (#4066); child reaped after a failed read (#4093); refusal without key material (#3902); hook verdicts fail closed (#3930); locked dependencies past advisories (#3894).
Utilities
- Registries and schemas. Versioned overrides for immutable registries (#3730); literal blocks for multi-line text (#3814); shared fence extraction (#3777).
- Concurrency and helpers.
maybe_awaitkeyword classifier (#3785); callback owners freed (#3826);DataLoggerexit callback (#3946); shared helpers reused (#3751).
Design records and docs
- ADR-0136. lionhub move, acceptance, merged-change notes, Amendments 1 and 2 (#3757, #3762, #3765, #3773, #3781).
- ADR-0137 to ADR-0140. Cost subsection accepted (#3776); Studio health route serves the port proof (#3784); CLI package location and citations (#3798, #4034, #4080); provider discovery contract (#4081, #4074).
- Other ADRs. ADR-0069 Amendments 2 and 3 proposed (#3796, #3813); ADR-0104 Amendment 4 (#3842); ADR-0126 Amendments 3, 5, 6 and 7 (#3803, #4028, #4032, #4043, #4114); ADR-0127 Amendment 1 (#3816); ADR-0132 verdict counts (#3808); ADR-0117 (#3800); ADR-0135 listing contract (#3797); ADR-0122 (#4035).
- Other records. Write-set sandbox bounds (#3780); command credential policy (#3822); checkpoint journal deltas (#3911); MCP grant resolution (#3919); terminal delivery (#3964); Linux identity (#3954, #3959); repointed citations (#3817); Studio live streams (#3810); pilot source mappings (#3742).
Tests, CI and internals
- Stabilized tests. Acknowledgement commits settle (#3997); timeout tests (#4005); lifecycle waits (#4037); slow-runner retry (#4110); lock retries (#4112).
- Bounds and coverage. Wall-clock bound dropped (#3823); setup bound (#4088); timing tests (#4091, #4102); hang guard (#4126); discovery and endpoint pins (#4083, #4101); overlapping coverage (#3766); resume outcomes (#3756); idle timeout (#3789); leak guards (#3909); race thread (#3775).
- Refactors. Runtime-state names in
iModel(#3778); log channels (#3782); graph predecessors (#3846); mirror row preparer (#3856); Studio paths folded (#3858); operator waits shared (#3860); import cycle broken (#4033). - CI and dependencies. Marketplace tests in the required job (#3772); 3.10 coverage step (#4122); action bumps (#3873, #3874, #3875).
- Internals. Feature ownership inventory and import report (#4020); changelog fragments (#4030, #4111, #4119, #4124).
- Integration merges, checkpoints and the release (#3819, #3830, #3867, #3882, #3887, #3896, #3897, #3907, #3916, #3917, #4071, #4107, #4118, #4125, #4140).
Upgrading
Code that does not use flat MCP names, _import_all_providers(), non-boolean gate results, undeclared MCP servers, credential variables in coding commands, run_sync offload keywords, empty-reply retries, timeout=0, the context-window fallback, or moved helpers needs no changes.
- Use namespaced MCP verbs, such as
agent.submit(#3847). - Add providers as manifest rows (#4108).
- Return
boolorGateResultfrom observer gates (#4001). - Declare MCP servers in the selected config (#3918).
- Restore needed variables in
command_env_allowlist(#3848). - Fix or remove an unreadable
settings.yaml(#3848). - Read the module path from loader errors (#3790).
- Bind
abandon_on_cancelorlimiterwithfunctools.partial(#3733, #3785). - Call the method again on an empty reply's outcome (#3763).
- Leave
timeoutunset, or pass a real limit (#3861). - Handle the context-window lookup errors (#4097).
- Pass
server_nameswithconfig_path(#3845). - Set
provider_error_typeorrejection_classonAccountRoutingErroronly with therequest_rejectedcode (#4123). - Import moved helpers and patch the new targets (#3768, #3771, #4039, #4045, #4069).
- Update imports to
lionhubpaths (#3752). - Restart every process that opens the state store (#3914).
- Check values in the user-wide
.env(#3783). - Check restored API requests against their schema (#4014).
- Use
a_add_message()for callable-instance hooks (#3906). - Read
run.failed.provider_nonretryablefor refusals (#4040, #4065). - Handle
FailedRoundErrorfrom cut-off replies (#3763). - Set an output limit where 32768 is not wanted (#3763).
- Rebuild agents using
--mcp-configor exclusive selections (#4012, #4053). - Read the paying account from
api_usage(#4096).
pip install --upgrade lionagi or uv add "lionagi>=0.37".
Full changelog: CHANGELOG.md · v0.36.0...v0.37.0