Skip to content

Commit f7b44ff

Browse files
a6b8claude
andcommitted
feat(elicitation): text-only responses become follow-up questions
When agent responds with text only (no tool calls), return as elicitation instead of forcing submit_answer. Enables multi-turn conversation where agent asks for missing info before acting. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e9de3eb commit f7b44ff

2 files changed

Lines changed: 29 additions & 9 deletions

File tree

src/agent/AgentLoop.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,32 @@ class AgentLoop {
151151
.some( ( block: any ) => block.type === 'tool_use' )
152152

153153
if( !hasToolUse || round > maxRounds ) {
154+
const textBlocks = content
155+
.filter( ( block: any ) => block.type === 'text' )
156+
.map( ( block: any ) => block.text )
157+
158+
const finalText = textBlocks.join( '\n' )
159+
160+
if( toolCallLog.length === 0 && !hasRequestedSubmit && round <= maxRounds ) {
161+
const duration = Date.now() - startTime
162+
163+
if( onRoundLog ) { onRoundLog( roundLog ) }
164+
165+
const result = {
166+
status: 'elicitation',
167+
query,
168+
result: { text: finalText },
169+
costs: { inputTokens: totalInputTokens, outputTokens: totalOutputTokens },
170+
metadata: { model, toolCalls: 0, llmRounds: round, duration }
171+
}
172+
173+
running = false
174+
175+
if( onStatus ) { onStatus( { status: 'completed', round, message: 'Agent needs more info (elicitation)' } ) }
176+
177+
return { result }
178+
}
179+
154180
if( !hasRequestedSubmit && toolCallLog.length > 0 && round <= maxRounds ) {
155181
hasRequestedSubmit = true
156182
messages.push( { role: 'assistant', content } )
@@ -164,11 +190,6 @@ class AgentLoop {
164190
continue
165191
}
166192

167-
const textBlocks = content
168-
.filter( ( block: any ) => block.type === 'text' )
169-
.map( ( block: any ) => block.text )
170-
171-
const finalText = textBlocks.join( '\n' )
172193
const duration = Date.now() - startTime
173194

174195
const result = AgentLoop

tests/unit/AgentLoop.test.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,10 @@ describe( 'AgentLoop', () => {
6666
maxTokens: 1024
6767
} )
6868

69-
expect( result.status ).toBe( 'success' )
69+
expect( result.status ).toBe( 'elicitation' )
7070
expect( result.query ).toBe( 'What should I buy?' )
7171
expect( result.metadata.llmRounds ).toBe( 1 )
7272
expect( result.metadata.toolCalls ).toBe( 0 )
73-
expect( result.costs.breakdown ).toHaveLength( 1 )
74-
expect( result.costs.breakdown[ 0 ].type ).toBe( 'llm' )
7573
} )
7674

7775

@@ -324,7 +322,8 @@ describe( 'AgentLoop', () => {
324322
maxTokens: 1024
325323
} )
326324

327-
expect( result.result ).toEqual( { key: 'value' } )
325+
expect( result.status ).toBe( 'elicitation' )
326+
expect( result.result ).toEqual( { text: 'Here is the result:\n```json\n{"key": "value"}\n```' } )
328327
} )
329328

330329

0 commit comments

Comments
 (0)