Skip to content

v0.1.0-alpha.23 — Agentic tool-use rescue paths + per-attempt timeout (additive)

Pre-release
Pre-release

Choose a tag to compare

@baabakk baabakk released this 25 Jun 01:12

What's in this release

Four additions targeting the agentic tool-use failure modes ADW's 2026-06-19 multi-team build-loop diagnostic surfaced. All additive, no breaking changes.

ASK 1 — Harmony tool-call extraction (adapter-openai)

parseHarmonyToolCalls() extracts one or more tool calls from a harmony-formatted message.reasoning_content string. When the standard tool_calls array is empty AND reasoning_content contains a parseable harmony tool call, the call is hoisted into the executable path. Zero extra LLM calls.

Closes the DeepInfra gpt-oss harmony tool-use gap that alpha.22 left open. Pre-alpha.23, runAgent treated harmony tool intent in reasoning_content as an empty assistant turn and terminated. Post-alpha.23, the tool call executes the same as a standard one.

The parser returns null gracefully when reasoning_content is empty, prose chain-of-thought, bare JSON without a tool name (the empirical {"path":"","depth":3} probe case), or contains malformed JSON. The zero-tool-call rescue (ASK 2) handles the prose-only case via a corrective retry.

ASK 2 — Zero-tool-call corrective rescue (adapter-openai)

When the model returns a clean completion (finish_reason: "stop" or "length") with prose content, empty tool_calls, and the request had a tools array — the adapter retries once with a corrective system message asking it to use the standard tool_calls format.

Closes the mimo-parasail prose case from ADW's diagnostic. Pre-alpha.23, mimo returned ~69 tokens of prose with zero tool_calls, runAgent terminated as completed, ADW promoted empty stubs to main. Post-alpha.23, the rescue gives the model one corrective shot before termination.

Five discriminators prevent over-firing: no tools in request → skip; tool_calls populated → skip; empty content → reasoning starvation (handled by alpha.22 path); reasoning_content populated → harmony case (handled by ASK 1); conversation includes a tool role message → model is summarizing, not failing → skip.

Single-shot retry only. If the rescue also returns prose, the consumer's orchestration is responsible (e.g., "planned ≠ written" guard at the workflow level).

ASK 3 — Telemetry tags (core)

Two new discriminators on the existing RetryReason union:

  • \"harmony-tool-call-extracted\" — adapter recovered a tool call from harmony channel (no retry; observability only)
  • \"zero-tool-call-prose-retry\" — adapter retried with corrective system message

Consumers filter the existing adapter onRetry hook on these values to distinguish "was rescued via X" from "clean zero-output (failover candidate)."

Per-attempt timeout helper (core)

RegistryOptions.perAttemptTimeoutMs wraps every provider attempt inside walkChain with an AbortController + timer. On timeout, the abort propagates to the adapter; the adapter throws ProviderUnavailableError; the Registry's shouldFallback catches it and walks to the next provider with a fresh timer.

const registry = createRegistryFromEnv({
  env: process.env,
  adapters: { /* ... */ },
  perAttemptTimeoutMs: 30000,  // 30s cap per provider
});

Per-attempt, not chain-wide. Each provider gets its own budget. Composes with user-supplied signal — both fire the same wrapped controller; shorter trigger wins.

Closes the ADW production wedge from 2026-06-19T15:40 UTC where mimo-parasail hit reasoning-starvation, retry expanded budget, then silently grinded for 3+ minutes with no timeout/failover. The AbortSignal infrastructure was already in place; this helper makes the per-attempt timeout pattern ergonomic.

What this does NOT fix

The Case B "under-production" pattern (model makes some tool calls then stops with the planned manifest incomplete) is NOT addressed at the adapter layer. The adapter sees a clean multi-call completion; only the orchestration knows the manifest is incomplete. ADW (and similar agentic orchestrators) should add a "planned ≠ written" guard at the workflow layer.

Backwards compatibility

All four additions are additive. Existing callers see no API surface changes. Two existing tests in adapter-openai (tool-schema-conversion, tool-use-edges) were updated to use mockResolvedValue instead of mockResolvedValueOnce so ASK 2's rescue retry has a target. Test intent (schema conversion correctness; termination logic) preserved.

Tests

  • 13 new harmony extraction tests (all parser branches + runAgent integration + telemetry emission)
  • 8 new zero-tool-call rescue tests (rescue fires correctly + 5 discriminator regression guards + single-shot guarantee + telemetry)
  • 8 new per-attempt timeout tests (hanging provider falls back, fast passes through, no timeout = backwards-compat, user signal composes, NOT chain-wide, onFallback emission, public field exposure)

Total: 792 unit tests pass (was 763 in alpha.22; +29, 0 regressions in any other suite).

Empirical sources

  • ADW Development_Logs.md commit b1eeee2 — DeepInfra harmony tool-use diagnostic
  • ADW production wedge incident 2026-06-19T15:40 UTC — mimo silent prose-only completion
  • Babak's raw 2-turn DeepInfra probe — empirical evidence of the reasoning_content shape
  • llm-ports#46 / discussion #50 — design discussion + ADW dev critique

Install

`pnpm add @llm-ports/core@alpha @llm-ports/adapter-openai@alpha`

All 7 publishable packages bumped to 0.1.0-alpha.23 (the unchanged adapters are revved to keep the @Alpha tag synchronized across the substrate).

What's NOT in this release (deferred)

  • Catalog architectural redesign (behavioral fingerprinting, catalog-as-optimization) — deferred to alpha.24
  • onValidationRetry Registry-level emission — deferred from alpha.21 planning
  • Streamed cost surfacing — deferred from alpha.21 planning
  • LP-REQ-01 resilient fallback preset — deferred from alpha.20.1 planning