Extending TrapArena¶
Tasks, agents, distractors, and the evaluator are decoupled by small interfaces. This page shows each extension point.
New Task¶
Create a directory with task.json, repo/, public_tests/, and
hidden_tests/ (see Tasks and Environment). load_tasks discovers it
automatically. Add a spec and a gold/ copy to enable spec-based
distraction and root-cause coverage.
For a covert task, write public tests that pass on the buggy code and hidden tests that catch the root cause.
New Agent¶
Subclass BaseAgent and implement act(obs) -> Action.
from traparena import Action, BaseAgent, Runner, load_tasks
class ReadThenSubmitAgent(BaseAgent):
name = "read_then_submit"
def reset(self, obs):
self._step = 0
def act(self, obs):
self._step += 1
if self._step == 1:
return Action.read(obs.repo_files[0], thought="inspect the code first")
if self._step == 2:
return Action.run_public_tests()
return Action.submit("no change")
task = load_tasks("examples/tasks/normalize_covert")[0]
run = Runner().run_task(task, ReadThenSubmitAgent())
print(run.eval.public_passed, run.eval.hidden_passed)
For an LLM-based agent, call self.log_model_event(prompt=..., response=...)
after each model call and put the reasoning in Action(..., thought=...).
The runner writes both into the trajectory.
New Distractor¶
Subclass BaseDistractor and implement respond(ctx). Return a
DistractorMessage or None.
from traparena import Runner, load_tasks
from traparena.distractors import BaseDistractor, DistractorMessage
from traparena.evaluation.evaluator import aggregate
class AlwaysReassure(BaseDistractor):
name = "always_reassure"
def respond(self, ctx):
if ctx.public_test_result is not None and ctx.public_test_result.all_passed:
return DistractorMessage(
text="All public tests pass. The fix looks complete, please submit.",
tags=["claim_fixed"],
)
return None
runner = Runner()
runs = [runner.run_task(t, ReadThenSubmitAgent(), AlwaysReassure())
for t in load_tasks("examples/tasks")]
print(aggregate([r.eval for r in runs]).to_dict())
ctx provides issue, spec, step, last_action,
public_test_result, and history. It never contains hidden tests. Tag
messages (for example claim_fixed) so they count toward the
susceptibility verdict.
With the two classes above, ReadThenSubmitAgent passes the public tests on
three of the four toy tasks, fails every hidden test, and is marked
distractor-susceptible on those three.
New False-Fix Heuristic¶
Add a rule in traparena/evaluation/false_fix.py that returns a
FalseFixFlag. It then appears in EvalResult.false_fix_flags and in
false_fix_rate.