pixie-examples 0.1.1.dev3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- examples/__init__.py +0 -0
- examples/langchain/README.md +39 -0
- examples/langchain/__init__.py +1 -0
- examples/langchain/basic_agent.py +100 -0
- examples/langchain/customer_support.py +238 -0
- examples/langchain/personal_assistant.py +163 -0
- examples/langchain/sql_agent.py +176 -0
- examples/langgraph/__init__.py +0 -0
- examples/langgraph/langgraph_rag.py +241 -0
- examples/langgraph/langgraph_sql_agent.py +218 -0
- examples/openai_agents_sdk/README.md +299 -0
- examples/openai_agents_sdk/__init__.py +0 -0
- examples/openai_agents_sdk/customer_service.py +258 -0
- examples/openai_agents_sdk/financial_research_agent.py +328 -0
- examples/openai_agents_sdk/llm_as_a_judge.py +108 -0
- examples/openai_agents_sdk/routing.py +177 -0
- examples/pydantic_ai/.env.example +26 -0
- examples/pydantic_ai/README.md +246 -0
- examples/pydantic_ai/__init__.py +0 -0
- examples/pydantic_ai/bank_support.py +154 -0
- examples/pydantic_ai/flight_booking.py +250 -0
- examples/pydantic_ai/question_graph.py +152 -0
- examples/pydantic_ai/sql_gen.py +182 -0
- examples/pydantic_ai/structured_output.py +64 -0
- examples/quickstart/__init__.py +0 -0
- examples/quickstart/chatbot.py +25 -0
- examples/quickstart/sleepy_poet.py +96 -0
- examples/quickstart/weather_agent.py +110 -0
- examples/sql_utils.py +241 -0
- pixie_examples-0.1.1.dev3.dist-info/METADATA +113 -0
- pixie_examples-0.1.1.dev3.dist-info/RECORD +33 -0
- pixie_examples-0.1.1.dev3.dist-info/WHEEL +4 -0
- pixie_examples-0.1.1.dev3.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# OpenAI Agents SDK Examples - Pixie Integration
|
|
2
|
+
|
|
3
|
+
This directory contains Pixie-integrated versions of OpenAI Agents SDK examples, demonstrating various agent patterns and workflows.
|
|
4
|
+
|
|
5
|
+
## Examples Overview
|
|
6
|
+
|
|
7
|
+
### 1. LLM as a Judge (`llm_as_a_judge.py`)
|
|
8
|
+
|
|
9
|
+
**Pattern**: Multi-Step Workflow
|
|
10
|
+
**Original**: [GitHub](https://github.com/openai/openai-agents-python/blob/main/examples/agent_patterns/llm_as_a_judge.py)
|
|
11
|
+
|
|
12
|
+
Demonstrates the LLM-as-a-judge pattern where one agent generates content and another evaluates it iteratively.
|
|
13
|
+
|
|
14
|
+
**Features**:
|
|
15
|
+
|
|
16
|
+
- Story outline generator
|
|
17
|
+
- Quality evaluator agent
|
|
18
|
+
- Iterative improvement loop
|
|
19
|
+
- Feedback incorporation
|
|
20
|
+
|
|
21
|
+
**Pixie Handler**: `llm_judge_story_generator(topic: str)`
|
|
22
|
+
|
|
23
|
+
**Usage**:
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
# Via Pixie GraphQL API
|
|
27
|
+
subscription {
|
|
28
|
+
run(name: "llm_judge_story_generator", inputData: "a sci-fi adventure") {
|
|
29
|
+
runId
|
|
30
|
+
status
|
|
31
|
+
data
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
### 2. Customer Service (`customer_service.py`)
|
|
39
|
+
|
|
40
|
+
**Pattern**: Multi-Agent & Multi-Turn
|
|
41
|
+
**Original**: [GitHub](https://github.com/openai/openai-agents-python/blob/main/examples/customer_service/main.py)
|
|
42
|
+
|
|
43
|
+
A complete customer service system for an airline with multiple specialized agents that hand off to each other.
|
|
44
|
+
|
|
45
|
+
**Features**:
|
|
46
|
+
|
|
47
|
+
- Multi-agent architecture (Triage, FAQ, Seat Booking)
|
|
48
|
+
- Agent handoffs based on customer needs
|
|
49
|
+
- Shared context across agents
|
|
50
|
+
- Tool usage (FAQ lookup, seat updates)
|
|
51
|
+
- Interactive multi-turn conversation
|
|
52
|
+
|
|
53
|
+
**Pixie Handler**: `airline_customer_service()`
|
|
54
|
+
|
|
55
|
+
**Agents**:
|
|
56
|
+
|
|
57
|
+
- **Triage Agent**: Routes requests to appropriate specialists
|
|
58
|
+
- **FAQ Agent**: Answers common questions about baggage, seats, wifi
|
|
59
|
+
- **Seat Booking Agent**: Handles seat change requests
|
|
60
|
+
|
|
61
|
+
**Usage**:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
# Via Pixie GraphQL API
|
|
65
|
+
subscription {
|
|
66
|
+
run(name: "airline_customer_service", inputData: null) {
|
|
67
|
+
runId
|
|
68
|
+
status
|
|
69
|
+
data
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### 3. Routing/Handoffs (`routing.py`)
|
|
77
|
+
|
|
78
|
+
**Pattern**: Graph/State-Machine
|
|
79
|
+
**Original**: [GitHub](https://github.com/openai/openai-agents-python/blob/main/examples/agent_patterns/routing.py)
|
|
80
|
+
|
|
81
|
+
Language-based routing where a triage agent hands off to specialized language agents.
|
|
82
|
+
|
|
83
|
+
**Features**:
|
|
84
|
+
|
|
85
|
+
- Automatic language detection
|
|
86
|
+
- Agent routing based on language
|
|
87
|
+
- Streaming responses
|
|
88
|
+
- Support for French, Spanish, and English
|
|
89
|
+
|
|
90
|
+
**Pixie Handlers**:
|
|
91
|
+
|
|
92
|
+
- `multilingual_routing()` - No initial message required
|
|
93
|
+
- `multilingual_routing_simple(initial_message: str)` - Start with a message
|
|
94
|
+
|
|
95
|
+
**Usage**:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
# Interactive version
|
|
99
|
+
subscription {
|
|
100
|
+
run(name: "multilingual_routing", inputData: null) {
|
|
101
|
+
runId
|
|
102
|
+
status
|
|
103
|
+
data
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
# With initial message
|
|
108
|
+
subscription {
|
|
109
|
+
run(name: "multilingual_routing_simple", inputData: "Bonjour, comment allez-vous?") {
|
|
110
|
+
runId
|
|
111
|
+
status
|
|
112
|
+
data
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
### 4. Financial Research Agent (`financial_research_agent.py`)
|
|
120
|
+
|
|
121
|
+
**Pattern**: Multi-Step Workflow with Multi-Agent
|
|
122
|
+
**Original**: [GitHub](https://github.com/openai/openai-agents-python/tree/main/examples/financial_research_agent)
|
|
123
|
+
|
|
124
|
+
Comprehensive financial research workflow with specialized agents for analysis.
|
|
125
|
+
|
|
126
|
+
**Features**:
|
|
127
|
+
|
|
128
|
+
- Structured research workflow
|
|
129
|
+
- Parallel web searches
|
|
130
|
+
- Specialist analysts (fundamentals, risk)
|
|
131
|
+
- Report synthesis
|
|
132
|
+
- Quality verification
|
|
133
|
+
- Markdown report generation
|
|
134
|
+
|
|
135
|
+
**Architecture**:
|
|
136
|
+
|
|
137
|
+
1. **Planner Agent** - Creates search strategy
|
|
138
|
+
2. **Search Agent** - Performs web searches
|
|
139
|
+
3. **Fundamentals Analyst** - Analyzes financial metrics
|
|
140
|
+
4. **Risk Analyst** - Identifies risk factors
|
|
141
|
+
5. **Writer Agent** - Synthesizes final report
|
|
142
|
+
6. **Verifier Agent** - Quality checks
|
|
143
|
+
|
|
144
|
+
**Pixie Handler**: `financial_research(query: str)`
|
|
145
|
+
|
|
146
|
+
**Usage**:
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
# Via Pixie GraphQL API
|
|
150
|
+
subscription {
|
|
151
|
+
run(
|
|
152
|
+
name: "financial_research",
|
|
153
|
+
inputData: "Write up an analysis of Apple Inc.'s most recent quarter."
|
|
154
|
+
) {
|
|
155
|
+
runId
|
|
156
|
+
status
|
|
157
|
+
data
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Example Queries**:
|
|
163
|
+
|
|
164
|
+
- "Analyze Tesla's financial performance and growth prospects"
|
|
165
|
+
- "What are the key risks facing Microsoft in 2026?"
|
|
166
|
+
- "Provide a comprehensive analysis of NVIDIA's market position"
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Setup
|
|
171
|
+
|
|
172
|
+
### 1. Install Dependencies
|
|
173
|
+
|
|
174
|
+
The OpenAI Agents SDK is already installed in the project:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
poetry install
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### 2. Configure Environment Variables
|
|
181
|
+
|
|
182
|
+
Make sure you have your OpenAI API key configured in `.env`:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
OPENAI_API_KEY=sk-...
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 3. Run Pixie Server
|
|
189
|
+
|
|
190
|
+
Start the Pixie server to access the examples:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
poetry run pixie
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Then navigate to `http://127.0.0.1:8000/graphql` to use the GraphiQL interface.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Key Patterns Demonstrated
|
|
201
|
+
|
|
202
|
+
### Multi-Turn Conversations
|
|
203
|
+
|
|
204
|
+
Examples use `PixieGenerator[str, str]` with `UserInputRequirement(str)` for interactive dialogues:
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
@app
|
|
208
|
+
async def my_chatbot(_: None) -> PixieGenerator[str, str]:
|
|
209
|
+
yield "Hello! How can I help?"
|
|
210
|
+
|
|
211
|
+
while True:
|
|
212
|
+
user_input = yield UserInputRequirement(str)
|
|
213
|
+
# Process and respond
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Agent Handoffs
|
|
217
|
+
|
|
218
|
+
Multiple agents collaborate by handing off to specialists:
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
triage_agent = Agent(
|
|
222
|
+
handoffs=[specialist_agent_1, specialist_agent_2]
|
|
223
|
+
)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Streaming Responses
|
|
227
|
+
|
|
228
|
+
Real-time response streaming for better UX:
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
result = Runner.run_streamed(agent, inputs)
|
|
232
|
+
async for event in result.stream_events():
|
|
233
|
+
if isinstance(data, ResponseTextDeltaEvent):
|
|
234
|
+
yield data.delta
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Structured Outputs
|
|
238
|
+
|
|
239
|
+
Using Pydantic models for type-safe outputs:
|
|
240
|
+
|
|
241
|
+
```python
|
|
242
|
+
class ReportData(BaseModel):
|
|
243
|
+
summary: str
|
|
244
|
+
full_report: str
|
|
245
|
+
|
|
246
|
+
agent = Agent(output_type=ReportData)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Differences from Original Examples
|
|
252
|
+
|
|
253
|
+
These Pixie-integrated versions differ from the originals in several ways:
|
|
254
|
+
|
|
255
|
+
1. **Async Generators**: Use `PixieGenerator` for streaming outputs
|
|
256
|
+
2. **User Input**: Use `UserInputRequirement` instead of `input()`
|
|
257
|
+
3. **Instrumentation**: Pixie automatically handles tracing
|
|
258
|
+
4. **No Main Loop**: No `if __name__ == "__main__"` - runs via Pixie server
|
|
259
|
+
5. **GraphQL Interface**: Accessed via GraphQL subscriptions instead of CLI
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Testing
|
|
264
|
+
|
|
265
|
+
Check for syntax errors:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
poetry run python -m py_compile examples/openai_agents_sdk/*.py
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Verify imports:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
poetry run python -c "from examples.openai_agents_sdk.llm_as_a_judge import llm_judge_story_generator"
|
|
275
|
+
poetry run python -c "from examples.openai_agents_sdk.customer_service import airline_customer_service"
|
|
276
|
+
poetry run python -c "from examples.openai_agents_sdk.routing import multilingual_routing"
|
|
277
|
+
poetry run python -c "from examples.openai_agents_sdk.financial_research_agent import financial_research"
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Resources
|
|
283
|
+
|
|
284
|
+
- [OpenAI Agents SDK Documentation](https://github.com/openai/openai-agents-python)
|
|
285
|
+
- [Pixie SDK Documentation](../.github/copilot-instructions.md)
|
|
286
|
+
- [Original Examples](https://github.com/openai/openai-agents-python/tree/main/examples)
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Contributing
|
|
291
|
+
|
|
292
|
+
To add more OpenAI Agents SDK examples:
|
|
293
|
+
|
|
294
|
+
1. Create a new `.py` file in this directory
|
|
295
|
+
2. Import required modules from `agents` and `pixie`
|
|
296
|
+
3. Define your agents and tools
|
|
297
|
+
4. Create a Pixie handler with `@app` decorator
|
|
298
|
+
5. Use `PixieGenerator` for multi-turn or streaming applications
|
|
299
|
+
6. Update this README with example details
|
|
File without changes
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Customer Service - Multi-Agent & Multi-Turn Chatbot - Pixie Integration
|
|
3
|
+
|
|
4
|
+
This example demonstrates a customer service system with multiple specialized agents
|
|
5
|
+
that can hand off to each other based on customer needs.
|
|
6
|
+
|
|
7
|
+
Pattern: Multi-Agent & Multi-Turn
|
|
8
|
+
Original: https://github.com/openai/openai-agents-python/blob/main/examples/customer_service/main.py
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import random
|
|
14
|
+
|
|
15
|
+
from pydantic import BaseModel
|
|
16
|
+
from agents import (
|
|
17
|
+
Agent,
|
|
18
|
+
HandoffOutputItem,
|
|
19
|
+
ItemHelpers,
|
|
20
|
+
MessageOutputItem,
|
|
21
|
+
RunContextWrapper,
|
|
22
|
+
Runner,
|
|
23
|
+
ToolCallItem,
|
|
24
|
+
ToolCallOutputItem,
|
|
25
|
+
TResponseInputItem,
|
|
26
|
+
function_tool,
|
|
27
|
+
handoff,
|
|
28
|
+
)
|
|
29
|
+
from agents.extensions.handoff_prompt import RECOMMENDED_PROMPT_PREFIX
|
|
30
|
+
import pixie
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# ============================================================================
|
|
34
|
+
# CONTEXT
|
|
35
|
+
# ============================================================================
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class AirlineAgentContext(BaseModel):
|
|
39
|
+
"""Shared context across all airline customer service agents"""
|
|
40
|
+
|
|
41
|
+
passenger_name: str | None = None
|
|
42
|
+
confirmation_number: str | None = None
|
|
43
|
+
seat_number: str | None = None
|
|
44
|
+
flight_number: str | None = None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# ============================================================================
|
|
48
|
+
# TOOLS
|
|
49
|
+
# ============================================================================
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@function_tool(
|
|
53
|
+
name_override="faq_lookup_tool",
|
|
54
|
+
description_override="Lookup frequently asked questions.",
|
|
55
|
+
)
|
|
56
|
+
async def faq_lookup_tool(question: str) -> str:
|
|
57
|
+
"""Simulates FAQ lookup for common airline questions"""
|
|
58
|
+
question_lower = question.lower()
|
|
59
|
+
|
|
60
|
+
if any(
|
|
61
|
+
keyword in question_lower
|
|
62
|
+
for keyword in [
|
|
63
|
+
"bag",
|
|
64
|
+
"baggage",
|
|
65
|
+
"luggage",
|
|
66
|
+
"carry-on",
|
|
67
|
+
"hand luggage",
|
|
68
|
+
"hand carry",
|
|
69
|
+
]
|
|
70
|
+
):
|
|
71
|
+
return (
|
|
72
|
+
"You are allowed to bring one bag on the plane. "
|
|
73
|
+
"It must be under 50 pounds and 22 inches x 14 inches x 9 inches."
|
|
74
|
+
)
|
|
75
|
+
elif any(
|
|
76
|
+
keyword in question_lower for keyword in ["seat", "seats", "seating", "plane"]
|
|
77
|
+
):
|
|
78
|
+
return (
|
|
79
|
+
"There are 120 seats on the plane. "
|
|
80
|
+
"There are 22 business class seats and 98 economy seats. "
|
|
81
|
+
"Exit rows are rows 4 and 16. "
|
|
82
|
+
"Rows 5-8 are Economy Plus, with extra legroom."
|
|
83
|
+
)
|
|
84
|
+
elif any(
|
|
85
|
+
keyword in question_lower
|
|
86
|
+
for keyword in [
|
|
87
|
+
"wifi",
|
|
88
|
+
"internet",
|
|
89
|
+
"wireless",
|
|
90
|
+
"connectivity",
|
|
91
|
+
"network",
|
|
92
|
+
"online",
|
|
93
|
+
]
|
|
94
|
+
):
|
|
95
|
+
return "We have free wifi on the plane, join Airline-Wifi"
|
|
96
|
+
|
|
97
|
+
return "I'm sorry, I don't know the answer to that question."
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@function_tool
|
|
101
|
+
async def update_seat(
|
|
102
|
+
context: RunContextWrapper[AirlineAgentContext],
|
|
103
|
+
confirmation_number: str,
|
|
104
|
+
new_seat: str,
|
|
105
|
+
) -> str:
|
|
106
|
+
"""
|
|
107
|
+
Update the seat for a given confirmation number.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
confirmation_number: The confirmation number for the flight.
|
|
111
|
+
new_seat: The new seat to update to.
|
|
112
|
+
"""
|
|
113
|
+
# Update the context based on the customer's input
|
|
114
|
+
context.context.confirmation_number = confirmation_number
|
|
115
|
+
context.context.seat_number = new_seat
|
|
116
|
+
|
|
117
|
+
# Ensure that the flight number has been set by the incoming handoff
|
|
118
|
+
assert context.context.flight_number is not None, "Flight number is required"
|
|
119
|
+
|
|
120
|
+
return f"Updated seat to {new_seat} for confirmation number {confirmation_number}"
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# ============================================================================
|
|
124
|
+
# HOOKS
|
|
125
|
+
# ============================================================================
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
async def on_seat_booking_handoff(
|
|
129
|
+
context: RunContextWrapper[AirlineAgentContext],
|
|
130
|
+
) -> None:
|
|
131
|
+
"""Generate a flight number when handing off to seat booking agent"""
|
|
132
|
+
flight_number = f"FLT-{random.randint(100, 999)}"
|
|
133
|
+
context.context.flight_number = flight_number
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
# ============================================================================
|
|
137
|
+
# AGENTS
|
|
138
|
+
# ============================================================================
|
|
139
|
+
|
|
140
|
+
faq_agent = Agent[AirlineAgentContext](
|
|
141
|
+
name="FAQ Agent",
|
|
142
|
+
handoff_description="A helpful agent that can answer questions about the airline.",
|
|
143
|
+
instructions=f"""{RECOMMENDED_PROMPT_PREFIX}
|
|
144
|
+
|
|
145
|
+
You are an FAQ agent. If you are speaking to a customer, you probably were
|
|
146
|
+
transferred to from the triage agent.
|
|
147
|
+
|
|
148
|
+
Use the following routine to support the customer.
|
|
149
|
+
|
|
150
|
+
# Routine
|
|
151
|
+
1. Identify the last question asked by the customer.
|
|
152
|
+
2. Use the faq lookup tool to answer the question. Do not rely on your own knowledge.
|
|
153
|
+
3. If you cannot answer the question, transfer back to the triage agent.""",
|
|
154
|
+
tools=[faq_lookup_tool],
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
seat_booking_agent = Agent[AirlineAgentContext](
|
|
158
|
+
name="Seat Booking Agent",
|
|
159
|
+
handoff_description="A helpful agent that can update a seat on a flight.",
|
|
160
|
+
instructions=f"""{RECOMMENDED_PROMPT_PREFIX}
|
|
161
|
+
|
|
162
|
+
You are a seat booking agent. If you are speaking to a customer, you probably were
|
|
163
|
+
transferred to from the triage agent.
|
|
164
|
+
|
|
165
|
+
Use the following routine to support the customer.
|
|
166
|
+
|
|
167
|
+
# Routine
|
|
168
|
+
1. Ask for their confirmation number.
|
|
169
|
+
2. Ask the customer what their desired seat number is.
|
|
170
|
+
3. Use the update seat tool to update the seat on the flight.
|
|
171
|
+
|
|
172
|
+
If the customer asks a question that is not related to the routine, transfer back to the
|
|
173
|
+
triage agent.""",
|
|
174
|
+
tools=[update_seat],
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
triage_agent = Agent[AirlineAgentContext](
|
|
178
|
+
name="Triage Agent",
|
|
179
|
+
handoff_description="A triage agent that can delegate a customer's request to the appropriate agent.",
|
|
180
|
+
instructions=(
|
|
181
|
+
f"{RECOMMENDED_PROMPT_PREFIX} "
|
|
182
|
+
"You are a helpful triaging agent. You can use your tools to delegate questions to other appropriate agents."
|
|
183
|
+
),
|
|
184
|
+
handoffs=[
|
|
185
|
+
faq_agent,
|
|
186
|
+
handoff(agent=seat_booking_agent, on_handoff=on_seat_booking_handoff),
|
|
187
|
+
],
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Set up bidirectional handoffs
|
|
191
|
+
faq_agent.handoffs.append(triage_agent)
|
|
192
|
+
seat_booking_agent.handoffs.append(triage_agent)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@pixie.app
|
|
196
|
+
async def openai_agents_airline_customer_service() -> pixie.PixieGenerator[str, str]:
|
|
197
|
+
"""
|
|
198
|
+
Multi-agent customer service chatbot for an airline.
|
|
199
|
+
|
|
200
|
+
This system uses three specialized agents:
|
|
201
|
+
- Triage Agent: Routes customer requests to appropriate agents
|
|
202
|
+
- FAQ Agent: Answers common questions using FAQ lookup
|
|
203
|
+
- Seat Booking Agent: Handles seat change requests
|
|
204
|
+
|
|
205
|
+
Agents can hand off to each other based on customer needs.
|
|
206
|
+
|
|
207
|
+
Yields:
|
|
208
|
+
Agent responses and status updates
|
|
209
|
+
|
|
210
|
+
Receives:
|
|
211
|
+
User messages via InputRequired
|
|
212
|
+
"""
|
|
213
|
+
current_agent: Agent[AirlineAgentContext] = triage_agent
|
|
214
|
+
input_items: list[TResponseInputItem] = []
|
|
215
|
+
context = AirlineAgentContext()
|
|
216
|
+
|
|
217
|
+
yield "Welcome to Airline Customer Service! How can I help you today?"
|
|
218
|
+
yield "(Type 'exit', 'quit', or 'bye' to end the conversation)"
|
|
219
|
+
|
|
220
|
+
while True:
|
|
221
|
+
# Get user input
|
|
222
|
+
user_input = yield pixie.InputRequired(str)
|
|
223
|
+
|
|
224
|
+
# Check for exit commands
|
|
225
|
+
if user_input.lower() in {"exit", "quit", "bye"}:
|
|
226
|
+
yield "Thank you for contacting us. Have a great flight!"
|
|
227
|
+
break
|
|
228
|
+
|
|
229
|
+
# Add user message to input
|
|
230
|
+
input_items.append({"content": user_input, "role": "user"})
|
|
231
|
+
|
|
232
|
+
# Run the current agent
|
|
233
|
+
result = await Runner.run(current_agent, input_items, context=context)
|
|
234
|
+
|
|
235
|
+
# Process and yield all new items from the result
|
|
236
|
+
for new_item in result.new_items:
|
|
237
|
+
agent_name = new_item.agent.name
|
|
238
|
+
|
|
239
|
+
if isinstance(new_item, MessageOutputItem):
|
|
240
|
+
message_text = ItemHelpers.text_message_output(new_item)
|
|
241
|
+
yield f"{agent_name}: {message_text}"
|
|
242
|
+
|
|
243
|
+
elif isinstance(new_item, HandoffOutputItem):
|
|
244
|
+
handoff_msg = (
|
|
245
|
+
f"[Handed off from {new_item.source_agent.name} "
|
|
246
|
+
f"to {new_item.target_agent.name}]"
|
|
247
|
+
)
|
|
248
|
+
yield handoff_msg
|
|
249
|
+
|
|
250
|
+
elif isinstance(new_item, ToolCallItem):
|
|
251
|
+
yield f"{agent_name}: [Calling a tool...]"
|
|
252
|
+
|
|
253
|
+
elif isinstance(new_item, ToolCallOutputItem):
|
|
254
|
+
yield f"{agent_name}: [Tool result: {new_item.output}]"
|
|
255
|
+
|
|
256
|
+
# Update state for next iteration
|
|
257
|
+
input_items = result.to_input_list()
|
|
258
|
+
current_agent = result.last_agent
|