fix: prevent agent tool protocol leakage
All checks were successful
Codex Template Compliance / template-compliance (pull_request) Successful in 8s
Build / test-and-image (pull_request) Successful in 52s

This commit is contained in:
2026-07-05 22:11:15 +02:00
parent 7e7ba4ae18
commit b42b3938c1
2 changed files with 89 additions and 8 deletions

View File

@@ -88,3 +88,42 @@ test('proactive notifications observe cooldown', async () => {
assert.equal(second.notify, false);
assert.equal(second.suppressed, 'cooldown');
});
test('step exhaustion uses a final-only prompt and returns synthesized evidence', async () => {
const prompts = [];
let call = 0;
const provider = {
isConfigured: true,
async complete(system) {
prompts.push(system);
call++;
return call === 1
? { text: JSON.stringify({ type: 'tool_call', tool: 'get_evidence', arguments: {}, rationale: 'Verify claim' }) }
: { text: JSON.stringify({ type: 'final', answer: 'The available evidence does not confirm the claim.', confidence: 'medium', evidence: ['evt-1'], notify: false, priority: 'routine' }) };
},
};
const agent = new TerminalAgent({
provider,
registry: new TerminalToolRegistry([{ name: 'get_evidence', handler: async () => [{ id: 'evt-1' }] }]),
maxSteps: 1,
});
const result = await agent.run('Is the claim confirmed?');
assert.equal(result.answer, 'The available evidence does not confirm the claim.');
assert.match(prompts[1], /Tool use is finished and unavailable/);
assert.doesNotMatch(prompts[1], /ALLOWLISTED TOOLS/);
});
test('repeated tool calls during finalization fail closed without leaking protocol JSON', async () => {
const provider = providerWith([{ type: 'tool_call', tool: 'get_evidence', arguments: {}, rationale: 'Keep searching' }]);
const agent = new TerminalAgent({
provider,
registry: new TerminalToolRegistry([{ name: 'get_evidence', handler: async () => [] }]),
maxSteps: 1,
});
const result = await agent.run('Wie sieht es mit dem Angriff aus?');
assert.match(result.answer, /nicht zuverlässig/);
assert.doesNotMatch(result.answer, /tool_call|get_evidence|rationale/i);
assert.equal(result.notify, false);
});