Skip to content

Expensive action space; the obstacle turns out to be the task class (7.6) - #200

Merged
joslat merged 1 commit into
mainfrom
findings/procedural-task-class
Aug 13, 2026
Merged

Expensive action space; the obstacle turns out to be the task class (7.6)#200
joslat merged 1 commit into
mainfrom
findings/procedural-task-class

Conversation

@joslat

@joslat joslat commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Fourth attempt, implementing what the third run's finding called for: twelve plausible decoy tools beside the four real ones, so calling everything costs sixteen invocations rather than four.

procedures  completion=100%  meanSteps=4.7  meanToolCalls=4.0
control     completion=100%  meanSteps=4.0  meanToolCalls=4.0
stepReduction=-16.7%   SHOWS BENEFIT: False

Both arms still called exactly the four right tools — selected out of sixteen without exploring, so the decoys cost nothing. And the procedural arm came out slightly worse (4.7 vs 4.0 steps), the recalled procedure adding context the agent had to read past.

Four attempts converge on a conclusion about the feature, not the benchmark. The obstacle was never the wording, the parameter names, the arbitrariness of the dependency, or the action-space size. It's that a competent model doesn't explore on this task class at all — it reads tool descriptions and selects correctly first time. Procedural memory has no exploration cost to remove because there is none.

Stated narrowly, because the broad version would be wrong:

For tasks where correct tool selection is inferable from tool descriptions — which is what a well-designed tool API is — a stored procedure saves nothing and carries a small context cost.

The place to look for benefit is tasks where the right action isn't inferable from the interface: undocumented sequencing, environment quirks, conventions learned from failure. Those are what a human writes a runbook for — and a runbook is what a procedure is.

Attempt Change Calls Verdict
1 Prerequisites in descriptions 3/3 read off the prose
2 Prerequisites removed 3/3 read off parameter names
3 Arbitrary dependency 4/4 called every tool
4 16-tool action space 4/4 selected correctly, no exploration

The instrument is sound and demonstrated across four runs. What it keeps reporting is that this task class has nothing for the feature to do — worth knowing before building a larger benchmark.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PgDgctPpbTziBNE2RT8VdE

Fourth attempt at making the procedural benchmark discriminate,
implementing what the third run's finding called for: twelve plausible
decoy tools beside the four real ones, so calling everything costs
sixteen invocations rather than four.

Both arms still called exactly the four right tools. The model selected
them out of sixteen without exploring, so the decoys cost nothing and
created no discovery to save. The procedural arm came out slightly WORSE
-- 4.7 steps against 4.0 -- the recalled procedure adding context the
agent then had to read past.

Four attempts now converge on a conclusion that is about the feature
rather than my benchmark. The obstacle was never the wording, the
parameter names, the arbitrariness of the dependency, or the size of the
action space. It is that a competent model does not explore on this
class of task at all: it reads tool descriptions and selects correctly
on the first attempt. Procedural memory has no exploration cost to
remove because there is none.

Stated narrowly, because the broad version would be wrong: for tasks
where correct tool selection is inferable from tool descriptions --
which is what a well-designed tool API is -- a stored procedure saves
nothing and carries a small context cost. The place to look for benefit
is tasks where the right action is not inferable from the interface:
undocumented sequencing, environment quirks, conventions learned from
failure rather than from a schema. Those are what a human writes a
runbook for, and a runbook is what a procedure is.

The instrument is sound and demonstrated working across four runs. What
it keeps reporting is that this task class has nothing for the feature
to do -- which is worth knowing before anyone builds a larger benchmark,
and is the finding to carry forward rather than the numbers.

453 LongMemEval tests green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PgDgctPpbTziBNE2RT8VdE
Copilot AI lite review requested due to automatic review settings August 13, 2026 03:27

Copilot AI 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.

Pull request overview

Expands the procedural-memory benchmark task’s tool action space by adding decoy tools, aiming to make “call everything” exploration meaningfully costly and to document the results of a fourth evaluation run.

Changes:

  • Added 12 decoy tools to ProceduralBenchmarkTask.CreateTools() via a new Decoys() helper.
  • Updated the unit test to expect 16 exposed tools.
  • Extended the review write-up documenting the fourth run and its conclusions.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
tools/AgentMemory.LongMemEval/ProceduralBenchmarkTask.cs Adds decoy tools to expand the benchmark toolset and record decoy invocations.
tests/AgentMemory.Tests.Unit.LongMemEval/ProceduralBenchmarkTaskTests.cs Updates expectations for the expanded tool list.
docs/reviews/procedural-benefit-run-prerequisite.md Documents the fourth run’s setup and findings.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 82 to 86
AIFunctionFactory.Create(PlaceHold),
AIFunctionFactory.Create(CheckServiceBulletin),
AIFunctionFactory.Create(Book),
.. Decoys(),
];
Comment on lines +102 to +116
new (string Name, string Description)[]
{
("check_seat_map", "Returns the seat map for a connection."),
("list_fare_classes", "Lists fare classes available on a connection."),
("get_station_facilities", "Returns facilities at a station."),
("check_loyalty_balance", "Returns a traveller's loyalty point balance."),
("list_connections", "Lists connections between two stations."),
("get_refund_policy", "Returns the refund policy for a fare class."),
("check_platform", "Returns the departure platform for a connection."),
("get_catering_menu", "Returns the catering menu for a connection."),
("list_baggage_rules", "Returns baggage allowance rules."),
("check_delay_history", "Returns recent punctuality for a connection."),
("get_carriage_layout", "Returns the carriage layout for a connection."),
("list_partner_operators", "Lists partner operators for a route."),
}
Comment on lines 187 to 193
public void ToolsAreExposedInProcedureOrder()
{
new ProceduralBenchmarkTask().CreateTools().Should().HaveCount(4);
// Four real tools plus twelve plausible decoys. The decoys are the third run's finding made
// concrete: with a small tool set an agent calls everything and skips discovery, so a stored
// procedure saves nothing and both arms tie.
new ProceduralBenchmarkTask().CreateTools().Should().HaveCount(16);
}
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.

2 participants