Skip to content

Commit 4a879bb

Browse files
authored
feat: add tool item convenience accessors (#1195)
1 parent bf28ecb commit 4a879bb

3 files changed

Lines changed: 103 additions & 0 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@openai/agents-core': patch
3+
---
4+
5+
feat: add tool item convenience accessors

packages/agents-core/src/items.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ export class RunToolCallItem extends RunItemBase {
6262
agent: this.agent.toJSON(),
6363
};
6464
}
65+
66+
get toolName(): string | undefined {
67+
return getStringProperty(this.rawItem, 'name');
68+
}
69+
70+
get callId(): string | undefined {
71+
return (
72+
getStringProperty(this.rawItem, 'callId') ??
73+
getStringProperty(this.rawItem, 'id')
74+
);
75+
}
6576
}
6677

6778
export class RunToolSearchCallItem extends RunItemBase {
@@ -122,6 +133,13 @@ export class RunToolCallOutputItem extends RunItemBase {
122133
output: toSmartString(this.output),
123134
};
124135
}
136+
137+
get callId(): string | undefined {
138+
return (
139+
getStringProperty(this.rawItem, 'callId') ??
140+
getStringProperty(this.rawItem, 'id')
141+
);
142+
}
125143
}
126144

127145
export class RunReasoningItem extends RunItemBase {
@@ -258,6 +276,11 @@ function getDefaultApprovalToolName(
258276
return resolvedToolName ?? rawItem.name;
259277
}
260278

279+
function getStringProperty(item: object, key: string): string | undefined {
280+
const value = (item as Record<string, unknown>)[key];
281+
return typeof value === 'string' ? value : undefined;
282+
}
283+
261284
export type RunItem =
262285
| RunMessageOutputItem
263286
| RunToolCallItem

packages/agents-core/test/items.test.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
FUNCTION_TOOL_NAMESPACE,
1818
FUNCTION_TOOL_NAMESPACE_DESCRIPTION,
1919
} from '../src/toolIdentity';
20+
import type * as protocol from '../src/types/protocol';
2021

2122
import { TEST_MODEL_MESSAGE, TEST_MODEL_FUNCTION_CALL } from './stubs';
2223

@@ -99,6 +100,43 @@ describe('items toJSON()', () => {
99100
agent: item.agent.toJSON(),
100101
});
101102
});
103+
104+
it('exposes the tool name and call id from function calls', () => {
105+
expect(item.toolName).toBe('test');
106+
expect(item.callId).toBe('test');
107+
});
108+
109+
it('exposes the hosted tool name and falls back to the item id for call id', () => {
110+
const hostedToolCall = new ToolCallItem(
111+
{
112+
id: 'hosted-call-id',
113+
type: 'hosted_tool_call',
114+
name: 'web_search_call',
115+
arguments: '{"query":"OpenAI"}',
116+
status: 'completed',
117+
},
118+
new Agent({ name: 'TestAgent' }),
119+
);
120+
121+
expect(hostedToolCall.toolName).toBe('web_search_call');
122+
expect(hostedToolCall.callId).toBe('hosted-call-id');
123+
});
124+
125+
it('returns undefined for missing tool names', () => {
126+
const shellCall = new ToolCallItem(
127+
{
128+
id: 'shell-id',
129+
type: 'shell_call',
130+
callId: 'shell-call-id',
131+
action: { commands: ['echo hi'] },
132+
status: 'completed',
133+
},
134+
new Agent({ name: 'TestAgent' }),
135+
);
136+
137+
expect(shellCall.toolName).toBeUndefined();
138+
expect(shellCall.callId).toBe('shell-call-id');
139+
});
102140
});
103141

104142
describe('ToolCallOutputItem', () => {
@@ -123,6 +161,43 @@ describe('items toJSON()', () => {
123161
output: item.output,
124162
});
125163
});
164+
165+
it('exposes the call id from tool call outputs', () => {
166+
expect(item.callId).toBe('test');
167+
});
168+
169+
it('falls back to the raw item id for call id', () => {
170+
const rawItem = {
171+
id: 'result-id',
172+
type: 'function_call_result',
173+
name: 'test',
174+
output: 'ok',
175+
status: 'completed',
176+
} as unknown as protocol.FunctionCallResultItem;
177+
const outputItem = new ToolCallOutputItem(
178+
rawItem,
179+
new Agent({ name: 'TestAgent' }),
180+
'ok',
181+
);
182+
183+
expect(outputItem.callId).toBe('result-id');
184+
});
185+
186+
it('returns undefined when no call id is available', () => {
187+
const rawItem = {
188+
type: 'function_call_result',
189+
name: 'test',
190+
output: 'ok',
191+
status: 'completed',
192+
} as unknown as protocol.FunctionCallResultItem;
193+
const outputItem = new ToolCallOutputItem(
194+
rawItem,
195+
new Agent({ name: 'TestAgent' }),
196+
'ok',
197+
);
198+
199+
expect(outputItem.callId).toBeUndefined();
200+
});
126201
});
127202

128203
describe('ReasoningItem', () => {

0 commit comments

Comments
 (0)