Skip to content

fix: LangChain/LangGraph parity audit — 40+ correctness fixes across session, cache, tool calling, reasoning, agent loop and local models - #95

Merged
senamakel merged 178 commits into
mainfrom
tinyagents-langchain-parity
Aug 8, 2026
Merged

fix: LangChain/LangGraph parity audit — 40+ correctness fixes across session, cache, tool calling, reasoning, agent loop and local models#95
senamakel merged 178 commits into
mainfrom
tinyagents-langchain-parity

Conversation

@senamakel

Copy link
Copy Markdown
Member

Summary

Closes a set of correctness defects found by auditing this crate against the
LangChain and LangGraph reference implementations, and ports the capabilities
that audit showed were missing. Six areas: session/persistence, cache, tool
calling, reasoning/structured output, the agent loop, and local models.

The dominant finding was disconnection, not absence. Fifteen subsystems were
correct, documented, unit-tested, and called by nothing:

SchemaCleanr (432 lines, zero callers) · the pairing-safe trimmer
(trim_messages_to_token_budget_with, test-only callers) · StreamChunk /
StreamMode (zero uses outside their module) · NoProgressTracker and
SuccessfulRepeatTracker (exported, never driven) · ToolMiddleware (trait and
onion, zero impls) · parse_retry_after_ms (test-only) ·
Checkpoint::pending_writes (always Vec::new()) · put_writes (absent) ·
StructuredExtractor.schema (stored, never read) · cache_creation_tokens
(summed and priced, never set) · protect_prompt_prefix (never read) ·
continuation_id (no reader) · ctx.request_control() (never called) ·
list_models() (never called from src/) · StreamChunk::Interrupt (never
constructed).

In two cases the safe implementation was the dead one and the unsafe one
was wired up — most damagingly in trimming, where the orphan-producing
trim_messages fed both the trim middleware and the fallback recovery path,
so a summarizer failure on a tool-heavy transcript upgraded a soft failure into
a hard provider 400.

Highest-impact fixes

Defect Effect before
sync_call_limits was fail-open a sub-agent given with_max_model_calls(3) ran 25
jitter: true zeroed the backoff the "hardened" retry config hammered rate-limited providers back-to-back
ModelFallbackMiddleware never re-resolved it re-invoked the same failing model per fallback name, emitting FallbackSelected events throughout
response cache key carried no model or provider one shared cache cross-served between a hosted and a local harness
compaction and all three trim strategies split tool pairs hard 400 on exactly the runs long enough to reach compaction
token estimation ignored tool_calls tool-only assistant turns estimated at 0; compaction never fired
structured output forced tool_choice every turn registered tools were never callable; the default path for a default profile
local models advertised a hosted context window llama3.2 claimed 128 000 against a real num_ctx of 2048; prompts silently truncated
strict: true sent with an unsanitized schema the crate's own doc example would 400
cache hits re-billed usage and cost BudgetMiddleware could abort a run on spend that never happened
the task-claim CAS ignored status a stale worker re-claimed a done task and stranded its dependents

Capabilities ported

put_writes/get_writes and the partial-failure resume protocol · a namespaced
Store with TTL, prefix search and batching · versioned schema migrations ·
LangGraph's checkpointer conformance invariants · local capability probing
(/api/show, /v1/models) with a native-tools degrade latch · a
provider-neutral ReasoningConfig · content_and_artifact tool returns ·
injected/hidden tool arguments · per-tool ToolErrorPolicy · a strict-mode
schema sanitizer at the conversion boundary · structured-output repair ladder
and schema validation · response-cache TTL, clear, byte bounds, stats, a
SQLite backend, prompt-cache breakpoint derivation and single-flight ·
AgentEvent failure variants · LimitBehavior::StopWithPartial · an
AgentEvent → StreamChunk projection · TinyAgentsError::ContextOverflow.

Two corrections to the audit itself

busy_timeout was not a bug. The audit claimed SQLite's default of 0 applied
because grep busy_timeout returned nothing in this crate. The grep was right;
the inference was not — rusqlite-0.40.1/src/inner_connection.rs:118 calls
sqlite3_busy_timeout(db, 5000) unconditionally on every Connection::open.
Caught because the regression test passed against unmodified code. The
explicit timeout is kept anyway (a load-bearing correctness property should not
rest on a transitive dep's undocumented default), but the docs and tests now say
that plainly instead of claiming a fix.

Six tests were pinning the bugs they covered, which is why several of these
shipped:

  • ModelFallbackMiddleware was only ever tested against a FakeModelBase that
    dispatched on the field the real base ignores.
  • sync_call_limits' only regression test pinned the loosening direction.
  • Two jitter contracts asserted the buggy multiplicative form.
  • provider_schema_parse_type_mismatch_errors asserted .expect("valid JSON extracts") on a value violating its schema — pinning "the schema is never
    read".
  • Two budget-reservation tests hard-coded token counts from a stale hand
    computation.
  • A concurrency test used #[tokio::test]'s default current-thread runtime, so
    the race it existed to catch could not interleave.

Each is fixed to test the real behaviour rather than deleted.

API Or Behavior Changes

Behaviour changes (deliberate, each pinned by a test):

  • RunPolicy::default(): UnknownToolPolicy and InvalidArgsPolicy now default
    to ReturnToolError instead of Fail. Previously {"city": 5} killed a run
    while an unparseable {city: recovered — an inconsistency with the crate's own
    unconditional recovery one branch earlier.
  • RetryPolicy::default(): backoff_sleep is now true; jitter is additive.
    Test convenience was setting production policy.
  • RunConfig::{max_model_calls, max_tool_calls} are now Option<usize> so an
    explicitly-set cap is distinguishable from the default; explicit ⇒ min
    (fail-closed), unset ⇒ policy wins.
  • Local runtime presets report max_input_tokens: None unless probed, rather
    than a model-id guess.
  • Cache hits no longer record usage or cost.

New public surface: ChatModel::cache_identity, Tool::{injected_arguments, error_policy}, ToolMessage::artifact, ModelResponse::served_from_cache,
ProviderError::retry_after_ms, ModelRequest::reasoning,
TinyAgentsError::ContextOverflow, Checkpointer::{put_writes, get_writes}
(defaulted, so external impls do not break), ResponseCache::{put_with_ttl, clear, stats} (defaulted likewise), SqliteResponseCache, SingleFlight,
AgentEvent::{ToolFailed, ModelFailed, SubAgentFailed}, LimitBehavior,
PartialRunOutcome, StructuredOutcome, prepare_tool_schemas,
count_tokens_approximately, project_event_for_modes,
OpenAiModel::{probe_local_profile, warm_up, validate_model, llama_cpp, vllm}.

Tests

2444 tests pass with --all-features (baseline 2197); 2238 on default features.
Every fix carries a regression test demonstrated failing at d82d022 before the
change — verified in detached worktrees, not git stash.

  • cargo fmt --check
  • cargo clippy --all-targets -- -D warnings
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo build --all-targets
  • cargo build --all-targets --all-features
  • cargo test — 2238 passed, 0 failed
  • cargo test --all-features — 2444 passed, 0 failed

Documentation

Module docs, README sections and doc comments were updated alongside each change
src/session/README.md (the busy_timeout correction above),
docs/modules/harness/cache.md's specified-but-unimplemented TTL/scope/stats
surface, and the PromptCacheGuardMiddleware field docs explaining why its
baseline is run-scoped.

Reviewer notes

Please squash-merge, and read the diff rather than the commit log. An
auto-commit hook fired throughout and generated messages that are actively
wrong: chore(harness): remove unused structured module for schema validation
and the ContextOverflow variant, fix(harness): correct agent loop cache layout handling for resolve_call_cap, fix(steering): clamp steering angle to valid range for an off-by-one in latch_pause (there is no steering angle in
this crate). One commit, 01a3bd8, snapshotted a deliberate red-before
experiment and really does disable cycle detection; it is reverted in f87dcc8
and the final state is correct and tested. The code is verified; the history
misdescribes it.

Known-not-done, deliberately:

  • Durable interrupt/resume (the largest remaining gap — an approval gate still
    ends the run, so a user re-runs from zero), ToolRetryMiddleware,
    Command-returning tools, NoProgressMiddleware, and streaming-mode wiring.
    Ran out of budget; not half-landed on purpose.
  • Per-channel versioned checkpoint writes. This is a state-model redesign, not a
    storage change — the executor's only bound is State: Send + Sync + 'static
    and the reducer treats state as one opaque value. The storage side is ready.
  • num_ctx/keep_alive reach Ollama via a native /api/chat warm-up that
    configures the runner subsequent /v1 calls reuse. That is a property of the
    server's runner reuse, not a guarantee of the OpenAI wire format; a native
    chat adapter is the real fix and is documented as a follow-up.
  • Six small cross-file handoffs blocked only by the file-ownership boundaries
    used while parallelising: StreamDiscarded and RunPaused event variants, a
    StructuredStrategy::JsonMode arm (blocked by an exhaustive match), tool-cap
    StopWithPartial, single-flight wiring, and replacing the FakeModelBase in
    middleware/library/test.rs.

senamakel and others added 30 commits August 8, 2026 19:00
…exes

Co-authored-by: Medulla <medulla@tinyhumans.ai>
…y_on predicate

Co-authored-by: Medulla <medulla@tinyhumans.ai>
Co-authored-by: Medulla <medulla@tinyhumans.ai>
…haustion

Co-authored-by: Medulla <medulla@tinyhumans.ai>
…-history summaries, and tool-result artifacts

Co-authored-by: Medulla <medulla@tinyhumans.ai>
…eckpoints

Co-authored-by: Medulla <medulla@tinyhumans.ai>
…cks transactional

Co-authored-by: Medulla <medulla@tinyhumans.ai>
…TS reindex

Co-authored-by: Medulla <medulla@tinyhumans.ai>
…, safe lineage walks

Co-authored-by: Medulla <medulla@tinyhumans.ai>
…tion, injected args, per-tool error policy

Co-authored-by: Medulla <medulla@tinyhumans.ai>
… API

Co-authored-by: Medulla <medulla@tinyhumans.ai>
…ddings/cohere.rs,src/harness/em

Checkpoint of work in progress, touching 30 files: src/harness/embeddings/cloud.rs,src/harness/embeddings/cohere.rs,src/harness/embeddings/mod.rs,src/harness/embeddings/ollama.rs,src/harness/embeddings/openai.rs,src/harness/limits/test.rs,src/harness/memory/mod.rs,src/harness/memory/types.rs,src/harness/model/mod.rs,src/harness/model/types.rs,src/harness/providers/openai/convert.rs,src/harness/providers/openai/mod.rs,src/harness/providers/openai/responses.rs,src/harness/providers/openai/sse.rs,src/harness/providers/openai/transport.rs,src/harness/providers/openai/types.rs,src/harness/providers/types.rs,src/harness/retry/jitter.rs,src/harness/retry/test.rs,src/harness/steering/test.rs,src/harness/store/mod.rs,src/harness/store/types.rs,src/session/migrations.rs,src/session/mod.rs,src/session/retention.rs,src/session/test.rs,src/harness/embeddings/http.rs,src/harness/providers/openai/local.rs,src/harness/providers/openai/local_test.rs,tests/context_and_schema_compaction.rs.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Adds a new test file covering the context and schema tool surface, verifying that the tools expose the expected context and schema information correctly. This ensures the tool surface behaves as intended and guards against regressions.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Adds a new test file covering runtime primitive resilience scenarios, ensuring core runtime operations behave correctly under edge cases and unexpected inputs.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a new conformance test suite to verify that the persistence module correctly handles all required operations and edge cases, ensuring consistent behaviour across different storage backends.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The conformance test helpers have been moved into a dedicated `conformance` submodule, so the import path is updated to reflect the new module structure.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The cycle detection logic in state history walks was incorrectly using a visited set that never triggered, so the warning branch has been replaced with a no-op to make the intent explicit. The copy_thread method now skips checking whether the target thread already exists by initializing an empty list, allowing overwrites without error. The test for max tokens trimming was updated to use a more realistic assistant message with both text and a tool call, and the token budget was reduced to better exercise the edge case where a tool result could be orphaned.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformatted the chained method call in the artifact assertion to improve readability without changing behavior.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The steering angle is now clamped to the minimum and maximum allowed values before being applied, preventing invalid inputs from causing unexpected behavior in the harness.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The pause commands were not receiving the checkpoint index, causing the recorded pause to reference the next checkpoint instead of the one currently being executed. The advance_checkpoint documentation is also updated to clarify that it returns the zero-based index of the current checkpoint.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add tests covering session save and restore behavior, including round-trip serialization and error handling for missing or corrupt session files.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Extract the repetitive inline construction of AgentTeamUpsert and AgentTeamTaskUpsert into dedicated helper functions, reducing duplication across the persistence session tests and making the test intent clearer.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Adds a new test file covering infrastructure resilience scenarios, ensuring that the feature behaves correctly under simulated failures and recovery conditions.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add end-to-end tests that verify the public API contracts remain stable across releases, ensuring that external consumers can rely on the documented interfaces without unexpected breakage.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a test suite covering the persistence store's save and load operations, including round-trip serialization and error handling for missing files. This ensures the store behaves correctly across common scenarios.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Introduce a new types module under the namespaced store harness to define shared data structures for namespaced storage operations. This provides a foundation for upcoming namespace-aware features without altering existing behavior.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformat several test assertions and function calls that exceeded the project's line length limit, wrapping them across multiple lines for consistency with the established code style. No behaviour was changed.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Fix two bugs in the checkpoint module: the cycle detection in state_history was always skipping the cycle warning because the check was negated, and copy_thread was using an empty vector instead of actually listing the target thread's existing checkpoints, causing it to always report the target as empty and allow overwriting an existing thread.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
When a namespace is not provided to the namespaced store, the store now returns an error instead of panicking. This ensures graceful handling of missing namespace configurations and improves robustness of the store initialization.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
senamakel and others added 22 commits August 8, 2026 21:38
Reformat the codebase with rustfmt to normalize line wrapping and import ordering across the agent loop, cache layout, memory, middleware library, and related wave2 tests. No behavioral changes are introduced.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
…ures

The ProviderError struct now includes a retry_after_ms field, so the test fixtures are updated to initialize it with None to keep the tests compiling and passing.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
…ol tests

The default policies for invalid tool arguments and unknown tool calls have changed to `ReturnToolError`, so the end-to-end tests that pin the fail-closed behavior now explicitly opt into `InvalidArgsPolicy::Fail` and `UnknownToolPolicy::Fail` via `RunPolicy`. This keeps the tests asserting the strict schema boundary and hard-stop behavior while accommodating the new permissive defaults.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add the missing import for InvalidArgsPolicy in the e2e middleware test file so the test can reference the policy type.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The cache documentation now reflects the current behavior of the agent loop, and the context middleware has been adjusted to align with the updated run loop logic. No functional changes are introduced; this is a routine maintenance update.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add documentation for the harness cache module, covering its purpose, configuration options, and usage examples to help users understand and leverage caching in their workflows.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The agent loop now treats an empty response from the agent as a no-op rather than attempting to process it, preventing a potential panic when the agent returns no output. This makes the loop more robust against unexpected agent behavior.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The budget middleware now correctly applies configured spending limits to requests, preventing overages by rejecting calls that would exceed the allocated quota. This closes a gap where limits were parsed but never enforced.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The run loop now treats an empty agent response as a no-op rather than attempting to process it, preventing a potential panic when the agent returns no content. This makes the loop more robust against unexpected empty outputs from the agent.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add tests covering loop cache accounting behavior in wave2, verifying that cache hits and misses are tracked correctly across loop iterations.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The test was accessing the `input_tokens` field directly on the snapshot's usage struct, but the field is nested under a `usage` property. This corrects the path so the assertion checks the actual token count as intended.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformatted the model registration in the cache accounting test to use a multi-line expression, improving readability without changing test behavior.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add tests covering the wave2 cache layout to verify the expected memory arrangement and access patterns.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Introduces the types module for the harness middleware layer, providing the foundational type definitions needed to support middleware functionality. This establishes the structural basis for future middleware implementations without altering existing behavior.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The context middleware in the library harness was no longer being used by any active code path, so it has been removed to reduce dead code and simplify the middleware stack.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The context middleware in the library harness was no longer being used by any active code path, so it has been removed to reduce dead code and simplify the middleware stack.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Introduces the middleware types module to the harness crate, providing the foundational type definitions needed for middleware support. This establishes the structural groundwork for future middleware functionality without altering existing behavior.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add integration tests covering the loading of local models from disk, verifying that the expected model files are found and parsed correctly. This ensures the local model path handling works as intended.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add integration tests covering the loading of local models from disk, verifying that the expected model files are found and parsed correctly. This ensures the local model path handling works as intended.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The guard held a single `previous` layout with no run scoping, so a shared
instance compared the last request of one run against the first request of
the next — two unrelated transcripts. Vacuously stable while comparison was
by segment id alone; a false positive on every multi-run sub-agent once the
comparison became content-aware.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add unit tests covering the wave2 cache store's core operations, including insertion, retrieval, and eviction scenarios. These tests verify the expected behavior of the cache store and help prevent regressions in future changes.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add test coverage for the wave2 cache store module, focusing on edge cases such as empty cache entries, concurrent access scenarios, and boundary conditions for cache expiration. This ensures the cache store behaves correctly under unusual or high-load conditions.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 156 files, which is 6 over the limit of 150.

To get a review, reduce the PR to 150 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to Pro+ to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 50aceff1-5d9c-415c-affe-59a69b547e8d

📥 Commits

Reviewing files that changed from the base of the PR and between d89275f and 5877372.

📒 Files selected for processing (156)
  • docs/modules/harness/cache.md
  • examples/agent_loop_tools.rs
  • src/error.rs
  • src/graph/checkpoint/file.rs
  • src/graph/checkpoint/mod.rs
  • src/graph/checkpoint/sqlite.rs
  • src/graph/checkpoint/test.rs
  • src/graph/checkpoint/types.rs
  • src/graph/compiled/executor.rs
  • src/graph/compiled/mod.rs
  • src/graph/compiled/routing.rs
  • src/graph/compiled/state_api.rs
  • src/graph/subagent_node/test.rs
  • src/graph/testkit/conformance.rs
  • src/harness/agent_loop/entry.rs
  • src/harness/agent_loop/mod.rs
  • src/harness/agent_loop/model_call.rs
  • src/harness/agent_loop/run_loop.rs
  • src/harness/agent_loop/test.rs
  • src/harness/agent_loop/tools.rs
  • src/harness/agent_loop/types.rs
  • src/harness/cache/hash.rs
  • src/harness/cache/key.rs
  • src/harness/cache/layout.rs
  • src/harness/cache/memory.rs
  • src/harness/cache/mod.rs
  • src/harness/cache/singleflight.rs
  • src/harness/cache/sqlite.rs
  • src/harness/cache/types.rs
  • src/harness/context/mod.rs
  • src/harness/context/test.rs
  • src/harness/context/types.rs
  • src/harness/embeddings/cloud.rs
  • src/harness/embeddings/cohere.rs
  • src/harness/embeddings/http.rs
  • src/harness/embeddings/mod.rs
  • src/harness/embeddings/ollama.rs
  • src/harness/embeddings/openai.rs
  • src/harness/events/mod.rs
  • src/harness/events/test.rs
  • src/harness/events/types.rs
  • src/harness/limits/mod.rs
  • src/harness/limits/test.rs
  • src/harness/limits/types.rs
  • src/harness/memory/mod.rs
  • src/harness/memory/types.rs
  • src/harness/message/mod.rs
  • src/harness/message/test.rs
  • src/harness/message/tokens.rs
  • src/harness/message/types.rs
  • src/harness/middleware/library/budget.rs
  • src/harness/middleware/library/context.rs
  • src/harness/middleware/library/test.rs
  • src/harness/middleware/test.rs
  • src/harness/middleware/types.rs
  • src/harness/model/mod.rs
  • src/harness/model/types.rs
  • src/harness/no_progress/mod.rs
  • src/harness/no_progress/test.rs
  • src/harness/no_progress/types.rs
  • src/harness/providers/mock.rs
  • src/harness/providers/openai/convert.rs
  • src/harness/providers/openai/local.rs
  • src/harness/providers/openai/local_test.rs
  • src/harness/providers/openai/mod.rs
  • src/harness/providers/openai/responses.rs
  • src/harness/providers/openai/sse.rs
  • src/harness/providers/openai/test.rs
  • src/harness/providers/openai/transport.rs
  • src/harness/providers/openai/types.rs
  • src/harness/providers/types.rs
  • src/harness/retry/jitter.rs
  • src/harness/retry/mod.rs
  • src/harness/retry/test.rs
  • src/harness/retry/types.rs
  • src/harness/runtime/types.rs
  • src/harness/steering/mod.rs
  • src/harness/steering/test.rs
  • src/harness/steering/types.rs
  • src/harness/store/mod.rs
  • src/harness/store/namespaced/mod.rs
  • src/harness/store/namespaced/test.rs
  • src/harness/store/namespaced/types.rs
  • src/harness/store/types.rs
  • src/harness/stream/mod.rs
  • src/harness/stream/project.rs
  • src/harness/stream/test.rs
  • src/harness/structured/mod.rs
  • src/harness/structured/repair.rs
  • src/harness/structured/types.rs
  • src/harness/structured/validate.rs
  • src/harness/subagent/test.rs
  • src/harness/summarization/mod.rs
  • src/harness/summarization/pairing.rs
  • src/harness/summarization/render.rs
  • src/harness/summarization/test.rs
  • src/harness/summarization/trim.rs
  • src/harness/summarization/types.rs
  • src/harness/tool/error_policy.rs
  • src/harness/tool/error_policy_test.rs
  • src/harness/tool/injected.rs
  • src/harness/tool/injected_test.rs
  • src/harness/tool/mod.rs
  • src/harness/tool/prompt.rs
  • src/harness/tool/prompt_test.rs
  • src/harness/tool/schema_prepare.rs
  • src/harness/tool/schema_prepare_test.rs
  • src/harness/tool/types.rs
  • src/session/README.md
  • src/session/migrations.rs
  • src/session/mod.rs
  • src/session/ops.rs
  • src/session/retention.rs
  • src/session/run_ledger/ops.rs
  • src/session/run_ledger/store.rs
  • src/session/store.rs
  • src/session/test.rs
  • tests/context_and_schema_compaction.rs
  • tests/context_and_schema_tool_surface.rs
  • tests/e2e_agent_graph.rs
  • tests/e2e_budget.rs
  • tests/e2e_fuzz_graph_agents.rs
  • tests/e2e_graph_subagent_node.rs
  • tests/e2e_graph_todos.rs
  • tests/e2e_harness_provider_contracts.rs
  • tests/e2e_middleware.rs
  • tests/e2e_observability.rs
  • tests/e2e_public_api_contracts.rs
  • tests/e2e_reasoning_and_selection.rs
  • tests/e2e_subagents.rs
  • tests/e2e_tool_policy.rs
  • tests/e2e_unknown_tool_policy.rs
  • tests/e2e_workspace_and_registry.rs
  • tests/feature_harness_agent_loop.rs
  • tests/feature_harness_structured.rs
  • tests/feature_infra_resilience.rs
  • tests/harness_agent_loop.rs
  • tests/live_local_models.rs
  • tests/persistence_conformance.rs
  • tests/persistence_session.rs
  • tests/persistence_store.rs
  • tests/provider_local_wire.rs
  • tests/runtime_primitives_resilience.rs
  • tests/wave2_cache_key_scope.rs
  • tests/wave2_cache_layout.rs
  • tests/wave2_cache_loop.rs
  • tests/wave2_cache_retry_after.rs
  • tests/wave2_cache_store.rs
  • tests/wave2_loop_cache_accounting.rs
  • tests/wave2_loop_control.rs
  • tests/wave2_loop_estimators.rs
  • tests/wave2_loop_limits.rs
  • tests/wave2_loop_recovery.rs
  • tests/wave2_loop_structured.rs
  • tests/wave2_tools_execution.rs
  • tests/wave2_tools_structured.rs

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c9e2330c06

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/graph/compiled/executor.rs
Comment thread src/harness/providers/openai/transport.rs
Comment thread src/graph/checkpoint/file.rs
Comment thread src/harness/cache/singleflight.rs Outdated
Comment thread src/harness/retry/mod.rs
Comment thread src/error.rs
Comment thread src/session/store.rs Outdated
Comment thread src/session/retention.rs Outdated
@senamakel senamakel self-assigned this Aug 8, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 587737219c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/harness/limits/mod.rs

/// Records one tool call and returns an error if the cap is exceeded.
pub fn record_tool_call(&mut self) -> Result<()> {
self.try_record_tool_call()?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stop tool execution when the partial limit is reached

When LimitBehavior::StopWithPartial is configured, try_record_tool_call() returns Ok(LimitOutcome::Stop(_)) after the cap, but this wrapper discards that outcome and returns Ok(()). The production admission path uses ctx.record_tool_call(), so every over-limit tool is still executed, no LimitReached event is emitted, and the documented placeholder results/counter rollback never happen. Propagate the outcome to the agent loop and add a focused tool-cap test.

AGENTS.md reference: AGENTS.md:L61-L65

Useful? React with 👍 / 👎.

Comment on lines +1842 to +1846
let tools = if self.native_tools_enabled() {
request
.tools
.iter()
.map(responses::translate_tool)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Decode Responses tool calls before advertising tools

When with_responses_api_primary() is used with registered tools, this now advertises them to the provider, which can return output items of type function_call. However, parse_responses_response() still hardcodes tool_calls: Vec::new() and finish_reason: "stop", so the agent loop treats that response as a final empty answer and never executes the requested tool. Either decode function_call/function_call_output structurally or keep this path prompt-guided until both directions are implemented, with a focused Responses tool-call contract test.

AGENTS.md reference: AGENTS.md:L61-L65

Useful? React with 👍 / 👎.

Comment on lines +169 to +170
"schema": schema,
"strict": strict,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prepare schemas before enabling strict Responses output

For the default hosted configuration, strict is true, but the Responses translation sends the caller's raw schema here. Common valid JSON Schemas with optional properties or without additionalProperties: false are rejected by OpenAI strict mode; the Chat Completions path already fixes exactly this by passing the schema through prepare_response_schema. Apply the same preparation on this path and cover the Responses request shape.

AGENTS.md reference: AGENTS.md:L61-L65

Useful? React with 👍 / 👎.

/// [`MiddlewareControl::kind`][crate::harness::context::MiddlewareControl::kind]
/// that mean "the run paused and is waiting for something external", and so
/// belong on [`StreamMode::Interrupts`] rather than in the debug firehose.
const INTERRUPTING_CONTROLS: [&str; 1] = ["interrupt"];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Project steering pauses onto the interrupt stream

When a steering Pause is applied, run_loop emits ControlApplied { control: "paused", ... }, but this allowlist recognizes only "interrupt". Consequently an event-stream consumer subscribed solely to StreamMode::Interrupts receives no notification that the run paused for human input; the event is classified as Debug and filtered out. Include the steering pause control in the interrupt projection.

Useful? React with 👍 / 👎.

@senamakel
senamakel merged commit fbfa4fd into main Aug 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant