Skip to content

lionagi v0.37.0

Latest

Choose a tag to compare

@ohdearquant ohdearquant released this 02 Nov 20:21
cdee8ad

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) with not_found. Use the namespaced verb instead, such as agent.submit or job.list. The catalog and server.info also drop their synonyms_removed_after field. (#3847)
  • _import_all_providers() removed. The private helper and its module list are gone from lionagi.service.connections.registry. Add a new built-in provider as a row in the hub's provider manifest instead. (#4108)
  • Session observer gates. A SessionObserver gate must return a bool or a GateResult. Other values, such as 1 or "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.json raises FileNotFoundError. Declare the server in the config you select, or provide the default file. Inline transport values must be exact built-in None, bool, int, float, str, list, tuple or dict values; Path, subclasses and cyclic structures raise ValueError. (#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_ENV and ENV from their child environments, GITHUB_TOKEN included. Patterns match anywhere in a name, so DATABASE_URL goes too. Restore a variable by its exact spelling in command_env_allowlist. (#3848)
  • Unreadable coding settings. If ~/.lionagi/settings.yaml cannot be read, or its secrets.lookup section is invalid, building a coding agent, a toolkit or BashTool raises ConfigurationError. Fix or remove the file or the section. (#3848)
  • Loader import errors. Application and provider module loaders raise a plain ImportError that names the module path. The original error is kept only as __cause__, so the outer .name and .path are None. A missing-module error is re-raised unchanged. (#3790)
  • run_sync keywords. lionagi.ln.concurrency.run_sync reserves abandon_on_cancel and limiter as offload controls, and rejects a non-boolean abandon_on_cancel. For a callable that takes either keyword, bind its arguments with functools.partial and pass that callable. (#3733, #3785)
  • Empty replies get no reformat request. parse(), and operate() and ReAct() through it, no longer send up to four reformat requests for a reply with no text, and return the handle_validation outcome at once. To keep the retries, call the method again on that outcome: the ExtractionError under "raise", or the UnparsedResponse of kind extraction under "return_value". (#3763)
  • Bash timeout=0. An explicit timeout=0 in CodingToolkit's bash tool now clamps to 1 ms. It used to mean the 30-second default. Leave timeout unset 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, ProviderActivationError or, for an unsupported manifest version, ProviderContractVersionError. It used to return the 128,000-token estimate. (#4097)
  • load_mcp_tools without server_names. With config_path=..., only the servers that file declares are registered. Pass server_names to choose servers explicitly. (#3845)
  • AccountRoutingError fields. Setting provider_error_type or rejection_class with any code other than request_rejected now raises ValueError. (#4123)
  • Moved private helpers and patch targets. Helpers moved out of lionagi.cli.mirror, lionagi.studio.cli and lionagi.cli.kill into lionagi.cli._mirror_service, lionagi.cli._schedule_parsing and lionagi.cli._kill_service, and kill helpers used outside that module lost their leading underscore. Patch lionagi.protocols.action.gate or lionagi._settings instead of the lionagi.agent modules. Patching lionagi.cli._logging.warn no longer reaches core code, which uses lionagi._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 authorize for decisions. No removal release is named. (#4018)
  • Session and toolkit arguments. Session.remove_branch(delete=...), exclude_clone and exclude_load on Session.to_df() and Session.concat_messages(), and CodingToolkit(notify_threshold=..., notify_max_tokens=...) now emit a DeprecationWarning when 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_admission and openai._chat_schemas now live at lionagi._provider_errors, lionagi.service.accounts._secret_resolution, lionagi.service._subagent_admission and lionagi.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.mcp and lionagi.operations.lndl_middle now live under lionhub, for example lionhub.providers and lionhub.lndl.middle. lionhub ships in the same distribution, so installs need nothing new. Each old path works until 2.0.0, returns the same module object and emits one DeprecationWarning naming the new path. The nine root exports, such as lionagi.LNDLOutput, warn on first use. lionagi._moved.MOVED lists 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_transitions until 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 lionhub path 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 .env under LIONAGI_HOME (~/.lionagi/.env by default). It ranks below the working directory's .env, .env.local and .secrets.env, and below the environment. A value there, such as LIONAGI_STATE_DB_URL or a provider key, reaches every lionagi process of that user. (#3783)
  • Anthropic output limit in li agent. An Anthropic API-model li agent run whose model names no output limit sends max_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_message hooks. is_coro_func now recognizes callable instances with an async __call__, and synchronous add_message() rejects them. Use a_add_message() for those hooks. (#3906)
  • Provider refusals. A turn the provider refuses is recorded as run.failed.provider_nonretryable, not run.failed.exception. Its FailedRoundError carries stop_reason and the provider's refusal detail. (#4040, #4065)
  • Cut-off replies. An API-model li agent run whose reply is cut off at the output limit, does not parse, or has no text is continued at most twice, then fails with FailedRoundError. It used to end as completed with the work undone. (#3763)
  • MCP config files. A server set read from --mcp-config is 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.json no longer records LIONAGI_API_ACCOUNT as api_account for a run that routes through the account router. The paying account is in api_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 GateDenied signal, 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 as artifact_turn_failed or artifact_turn_unused. (#3915)
  • Endpoint lookup. EndpointRegistry.match with no endpoint named resolves a catalog-declared provider to its default endpoint, whatever was imported first. list_providers() lists codex after the OpenAI endpoints instead of second. (#4104, #4108)
  • Linux li kill. On Linux, li kill keeps 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 studio keeps the daemon's launch bearer in localStorage, bound to the daemon's API base. It forgets the bearer on the first 401 that carried it, so a restarted daemon asks for li studio again. (#4116)
  • Pairing response. POST /api/studio/pair returns token_source, which is "launch" for the daemon's per-start launch bearer or "configured" when LIONAGI_STUDIO_AUTH_TOKEN is set. (#4116)
  • Loopback and port checks. li studio, the li schedule clients and the li doctor daemon check reach a daemon on localhost, 127.0.0.0/8 or ::1 without a configured proxy. li studio also checks that it can bind its port before it prints a pairing link. (#4117)
  • Terminal reconciliation (opt-in). With LIONAGI_STUDIO_TERMINAL_RECONCILE set 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=...) and ReviewEngine(stage_max_tokens={...}) set the Anthropic output limit per agent or review stage. (#3865)
  • Context folding. API chat and operate fold 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-calls loops show tools only as calls (#3801); known reads declared per turn, up to 16 (#3806).
  • Runs, launch and profiles. no_delivery_command failure (#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 PASS token 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); LionTool and 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_caching on AgentSpec and Engine places marks from earlier entries (#3811, #3866); cache read and write counts per request (#3926).
  • Cache placement. OpenAI stable prefix (#3920); cache_intent exported (#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); _config context tables (#4090); provider_catalog on match and iModel (#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.errors exceptions (#3948); root logger untouched (#4023); whitespace-only history skipped (#3815).

MCP server

  • Stdio handshake. Servers that close their pipe on a first non-initialize request 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 token exchange 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_markers moves to lionagi.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: write runs bash and editor under a Seatbelt policy, with the network off unless api_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_await keyword classifier (#3785); callback owners freed (#3826); DataLogger exit 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

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 bool or GateResult from 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_cancel or limiter with functools.partial (#3733, #3785).
  • Call the method again on an empty reply's outcome (#3763).
  • Leave timeout unset, or pass a real limit (#3861).
  • Handle the context-window lookup errors (#4097).
  • Pass server_names with config_path (#3845).
  • Set provider_error_type or rejection_class on AccountRoutingError only with the request_rejected code (#4123).
  • Import moved helpers and patch the new targets (#3768, #3771, #4039, #4045, #4069).
  • Update imports to lionhub paths (#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_nonretryable for refusals (#4040, #4065).
  • Handle FailedRoundError from cut-off replies (#3763).
  • Set an output limit where 32768 is not wanted (#3763).
  • Rebuild agents using --mcp-config or 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