Skip to content

Commit c2f9ad7

Browse files
xiazemintmc
andauthored
agents: Add more robust response handling to executor.go (tmc#1316)
* agents: fix handling of observation suffix in tool inputs Add test coverage to ensure the executor properly trims nObservation: suffix from tool inputs before passing them to tools. This prevents tools from receiving malformed input that includes the observation marker. - Add TestExecutorTrimsObservationSuffix to verify trimming behavior - Add test case in MRKL output parser for action inputs with observation suffix - Add tools field to testAgent to support tool testing --------- Co-authored-by: Travis Cline <travis.cline@gmail.com>
1 parent 2389d7a commit c2f9ad7

3 files changed

Lines changed: 69 additions & 2 deletions

File tree

agents/executor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func (e *Executor) doAction(
134134
}), nil
135135
}
136136

137-
observation, err := tool.Call(ctx, action.ToolInput)
137+
observation, err := tool.Call(ctx, strings.TrimSuffix(action.ToolInput, "\nObservation:"))
138138
if err != nil {
139139
return nil, err
140140
}

agents/executor_test.go

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type testAgent struct {
2323
err error
2424
inputKeys []string
2525
outputKeys []string
26+
tools []tools.Tool
2627

2728
recordedIntermediateSteps []schema.AgentStep
2829
recordedInputs map[string]string
@@ -50,7 +51,7 @@ func (a testAgent) GetOutputKeys() []string {
5051
}
5152

5253
func (a *testAgent) GetTools() []tools.Tool {
53-
return nil
54+
return a.tools
5455
}
5556

5657
func TestExecutorWithErrorHandler(t *testing.T) {
@@ -171,3 +172,59 @@ func TestExecutorWithOpenAIFunctionAgent(t *testing.T) {
171172
require.True(t, strings.Contains(result, "2012") || strings.Contains(result, "March"),
172173
"correct answer 2012 or March not in response")
173174
}
175+
176+
// mockTool implements the tools.Tool interface for testing
177+
type mockTool struct {
178+
name string
179+
description string
180+
receivedInputPtr *string
181+
}
182+
183+
func (m *mockTool) Name() string {
184+
return m.name
185+
}
186+
187+
func (m *mockTool) Description() string {
188+
return m.description
189+
}
190+
191+
func (m *mockTool) Call(_ context.Context, input string) (string, error) {
192+
*m.receivedInputPtr = input
193+
return "mock result", nil
194+
}
195+
196+
func TestExecutorTrimsObservationSuffix(t *testing.T) {
197+
t.Parallel()
198+
ctx := context.Background()
199+
200+
// Create a mock tool that records what input it receives
201+
var receivedInput string
202+
mockToolInst := &mockTool{
203+
name: "mock_tool",
204+
description: "A mock tool for testing",
205+
receivedInputPtr: &receivedInput,
206+
}
207+
208+
// Create a test agent that returns an action with trailing "\nObservation:"
209+
testAgent := &testAgent{
210+
actions: []schema.AgentAction{
211+
{
212+
Tool: "mock_tool",
213+
ToolInput: "test input\nObservation:",
214+
Log: "Action: mock_tool\nAction Input: test input\nObservation:",
215+
},
216+
},
217+
inputKeys: []string{"input"},
218+
outputKeys: []string{"output"},
219+
tools: []tools.Tool{mockToolInst},
220+
}
221+
222+
executor := agents.NewExecutor(testAgent, agents.WithMaxIterations(1))
223+
224+
_, err := chains.Call(ctx, executor, map[string]any{"input": "test question"})
225+
// We expect ErrNotFinished since our test agent doesn't provide a finish action
226+
require.ErrorIs(t, err, agents.ErrNotFinished)
227+
228+
// Verify that the tool received the input with "\nObservation:" trimmed off
229+
require.Equal(t, "test input", receivedInput, "Tool should receive input with \\nObservation: suffix trimmed")
230+
}

agents/markl_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ func TestMRKLOutputParser(t *testing.T) {
3636
expectedFinish: nil,
3737
expectedErr: nil,
3838
},
39+
{
40+
input: "Action: calculator\nAction Input: 5 + 3\nObservation:",
41+
expectedActions: []schema.AgentAction{{
42+
Tool: "calculator",
43+
ToolInput: "5 + 3\nObservation:",
44+
Log: "Action: calculator\nAction Input: 5 + 3\nObservation:",
45+
}},
46+
expectedFinish: nil,
47+
expectedErr: nil,
48+
},
3949
}
4050

4151
a := OneShotZeroAgent{}

0 commit comments

Comments
 (0)