Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion examples/tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ These examples demonstrate the hosted tools provided by the Agents SDK.
pnpm examples:tools-file-search
```

- `codex-tool.ts` – Wraps the Codex SDK as an agent tool and prints structured tracing output. Requires `OPENAI_API_KEY` and `CODEX_API_KEY` environment variables.

```bash
pnpm examples:tools-codex
```

- `web-search.ts` – Demonstrates `webSearchTool` for general web queries.

```bash
Expand All @@ -32,4 +38,4 @@ These examples demonstrate the hosted tools provided by the Agents SDK.

```bash
pnpm examples:tools-image-generation
```
```
111 changes: 111 additions & 0 deletions examples/tools/codex-tool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import {
Agent,
run,
withTrace,
type RunItem,
type RunToolCallOutputItem,
} from '@openai/agents';
import {
codexTool,
type CodexOutputSchemaDescriptor,
} from '@openai/agents-extensions';

type CodexToolOutput = {
threadId: string | null;
response: string;
usage: Record<string, unknown> | null;
};

function ensureEnvironmentVariables(): void {
const requiredVariables = ['OPENAI_API_KEY', 'CODEX_API_KEY'];
const missing = requiredVariables.filter((name) => !process.env[name]);

if (missing.length > 0) {
throw new Error(
`Missing required environment variable${missing.length > 1 ? 's' : ''}: ${missing.join(', ')}.`,
);
}
}

function isCodexToolOutputItem(
item: RunItem,
): item is RunToolCallOutputItem & { output: CodexToolOutput } {
if (item.type !== 'tool_call_output_item' || item.rawItem.name !== 'codex') {
return false;
}

const output = item.output as unknown;
if (typeof output !== 'object' || output === null) {
return false;
}

const maybeOutput = output as Partial<CodexToolOutput>;
return (
typeof maybeOutput.response === 'string' &&
(typeof maybeOutput.threadId === 'string' || maybeOutput.threadId === null)
);
}

const codexStructuredOutput: CodexOutputSchemaDescriptor = {
title: 'CodexToolResult',
properties: [
{
name: 'summary',
description: 'High-level summary of Codex actions and findings.',
schema: {
type: 'string',
},
},
{
name: 'commands',
description:
'Commands executed by Codex, in the order they were invoked.',
schema: {
type: 'array',
items: {
type: 'string',
},
},
},
],
required: ['summary'],
};

async function main(): Promise<void> {
ensureEnvironmentVariables();

const agent = new Agent({
name: 'Codex tool orchestrator',
instructions:
'You route workspace automation tasks through the codex tool. Always call the codex tool at least once before responding, and use it to run commands or inspect files before summarizing the results.',
tools: [codexTool({ outputSchema: codexStructuredOutput })],
});

const task =
'Call the codex tool to run `ls -1` in the current directory and summarize the output for the user.';

const result = await withTrace('Codex tool example', async () => {
console.log('Starting Codex tool run...\n');
return run(agent, task);
});

console.log(`Agent response:\n${String(result.finalOutput ?? '')}\n`);

const codexOutput = result.newItems.find(isCodexToolOutputItem);
if (codexOutput) {
const { threadId, response, usage } = codexOutput.output;
console.log('Codex tool call returned:');
console.log(` Thread ID: ${threadId ?? 'not provided'}`);
console.log(` Response: ${response}`);
if (usage) {
console.log(' Usage:', usage);
}
} else {
console.warn('The Codex tool did not produce a structured result.');
}
}

main().catch((error) => {
console.error(error);
process.exit(1);
});
2 changes: 2 additions & 0 deletions examples/tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
"name": "tools",
"dependencies": {
"@openai/agents": "workspace:*",
"@openai/agents-extensions": "workspace:*",
"playwright": "^1.55.1"
},
"scripts": {
"build-check": "tsc --noEmit",
"start:codex-tool": "tsx codex-tool.ts",
"start:computer-use": "tsx computer-use.ts",
"start:file-search": "tsx file-search.ts",
"start:web-search": "tsx web-search.ts",
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"examples:research-bot": "pnpm -F research-bot start",
"examples:financial-research-agent": "pnpm -F financial-research-agent start",
"examples:tools-computer-use": "pnpm -F tools start:computer-use",
"examples:tools-codex": "pnpm -F tools start:codex-tool",
"examples:tools-file-search": "pnpm -F tools start:file-search",
"examples:tools-web-search": "pnpm -F tools start:web-search",
"examples:tool-filter": "tsx examples/mcp/tool-filter-example.ts",
Expand Down
1 change: 1 addition & 0 deletions packages/agents-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ export type {
FunctionCallItem,
FunctionCallResultItem,
JsonSchemaDefinition,
JsonObjectSchemaStrict,
ReasoningItem,
ResponseStreamEvent,
SystemMessageItem,
Expand Down
1 change: 1 addition & 0 deletions packages/agents-core/src/tracing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export {
ConsoleSpanExporter,
} from './processor';
export { NoopSpan, Span } from './spans';
export type { CustomSpanData } from './spans';
export { NoopTrace, Trace } from './traces';
export { generateGroupId, generateSpanId, generateTraceId } from './utils';

Expand Down
1 change: 1 addition & 0 deletions packages/agents-extensions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"dependencies": {
"@ai-sdk/provider": "^2.0.0",
"@openai/agents-core": "workspace:*",
"@openai/codex-sdk": "^0.53.0",
"@types/ws": "^8.18.1",
"debug": "^4.4.0"
},
Expand Down
Loading
Loading