honcho/tests/llm
Tomas Sereikis 5535415e89 perf(llm): run one turn's tool calls concurrently instead of serially
A single assistant turn routinely requests several independent reads — a
dialectic turn typically emits `search_memory` and `search_messages` together —
but the loop awaited them one at a time, so the turn cost their sum when it only
needed to cost the slowest. Measured on a production `minimal` dialectic: 1.2s
in `search_memory`, then a further 1.9s in `search_messages`, both pure reads.

Measured across 42 production dialectic requests (103 iterations, 77 of them
multi-tool, 3.34 tool calls per iteration on average), running each turn's calls
concurrently would cut 11.3% of total wall-clock: median 9.3% per request, p90
29.7%, best case 51.0%. Only 4 of the 42 requests gain nothing.

This is safe because tool handlers own their sessions: each opens a short-lived
one via `tracked_db()`, and only the mutating handlers (`create_observations`,
`update_peer_card`, `delete_observations`) take `ctx.db_lock`, so concurrent
reads do not contend on shared state.

The per-call telemetry ContextVars move inside the task. `asyncio` copies the
context per task, so `set_current_tool_call_seq` and `set_last_tool_metadata`
now bind to their own call instead of being written and read across one shared
context — which the previous code could only keep straight by never overlapping.
`gather` preserves argument order, so `tool_results` and `all_tool_calls` stay in
the order the model asked for them.

Fan-out is capped at MAX_CONCURRENT_TOOL_CALLS (4). Production has produced 18
tool calls in one iteration, and firing all of them at once would mean that many
simultaneous embedding + pgvector queries on a single instance. The cap leaves
the measured common case fully parallel while bounding the tail.
2026-08-29 13:26:19 +03:00
..
test_backends fix(openai): fix content normalization in openai backend history adapter (#1064) 2026-08-26 12:14:32 -04:00
conftest.py Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
test_agent_tool_schemas.py Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
test_capture.py feat(telemetry): CloudEvents + Langfuse tracing as projections over a captured LLM stream (#845) 2026-07-02 16:49:53 -04:00
test_conversation.py Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
test_credentials.py Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
test_embedding_client.py fix: only classify genuine oversize input as a token-limit error (#791) 2026-08-25 09:45:01 -04:00
test_history_adapters.py fix(openai): fix content normalization in openai backend history adapter (#1064) 2026-08-26 12:14:32 -04:00
test_langfuse_trace_annotation.py feat(telemetry): CloudEvents + Langfuse tracing as projections over a captured LLM stream (#845) 2026-07-02 16:49:53 -04:00
test_model_config.py feat: add model config option for json_object mode (#820) 2026-06-23 10:42:03 -04:00
test_registry.py perf: lazy-load provider SDKs to cut idle memory per process (#1011) 2026-08-12 21:39:12 -04:00
test_request_builder.py fix(llm): support per-request provider timeouts (#832) 2026-08-04 12:43:00 -04:00
test_telemetry_agent_iteration.py feat(telemetry): CloudEvents + Langfuse tracing as projections over a captured LLM stream (#845) 2026-07-02 16:49:53 -04:00
test_telemetry_agent_tool_call.py feat: add new cloudevents for api routes (#637) 2026-05-20 18:25:30 -04:00
test_telemetry_llm_call.py perf: lazy-load provider SDKs to cut idle memory per process (#1011) 2026-08-12 21:39:12 -04:00
test_tool_loop_parallel.py perf(llm): run one turn's tool calls concurrently instead of serially 2026-08-29 13:26:19 +03:00
test_tool_loop_reasoning_content.py fix(openai): fix content normalization in openai backend history adapter (#1064) 2026-08-26 12:14:32 -04:00
test_tool_loop_truncation.py feat: add new cloudevents for api routes (#637) 2026-05-20 18:25:30 -04:00