Merge changes v1

This commit is contained in:
akhisud3195 2025-03-25 15:37:51 +05:30 committed by Ramnique Singh
parent b2fd9bf877
commit 24efe0e887
45 changed files with 2940 additions and 294 deletions

View file

@ -1,74 +0,0 @@
[tool.poetry]
name = "agents"
version = "0.1.0"
description = "RowBoat Labs Agent OS"
authors = ["Akhilesh <akhilesh@rowboatlabs.com>"]
license = "MIT"
readme = "README.md"
homepage = "https://github.com/rowboatlabs/agents"
package-mode = false
[tool.poetry.dependencies]
# Python
python = ">=3.10,<4.0"
# Dependencies
aiohttp = "^3.9.3"
annotated-types = "^0.7.0"
anyio = "^4.6.2"
beautifulsoup4 = "^4.12.3"
blinker = "^1.8.2"
certifi = "^2024.8.30"
charset-normalizer = "^3.4.0"
click = "^8.1.7"
distro = "^1.9.0"
dnspython = "^2.7.0"
et_xmlfile = "^2.0.0"
eval_type_backport = "^0.2.0"
firecrawl = "^1.4.0"
Flask = "^3.0.3"
gunicorn = "^23.0.0"
h11 = "^0.14.0"
httpcore = "^1.0.6"
httpx = "^0.27.2"
idna = "^3.10"
itsdangerous = "^2.2.0"
Jinja2 = "^3.1.4"
jiter = "^0.6.1"
jsonpath-python = "^1.0.6"
lxml = "^5.3.0"
markdownify = "^0.13.1"
MarkupSafe = "^3.0.2"
mcp = "*"
motor = "^3.7.0"
mypy-extensions = "^1.0.0"
nest-asyncio = "^1.6.0"
numpy = "^2.1.2"
openai = "^1.52.2"
openai-agents = "^0.0.4"
openpyxl = "^3.1.5"
pandas = "^2.2.3"
pydantic = "^2.9.2"
pydantic_core = "^2.23.4"
pymongo = "^4.10.1"
python-dateutil = "^2.8.2"
python-docx = "^1.1.2"
python-dotenv = "^1.0.1"
pytz = "^2024.2"
qdrant_client = "^1.13.3"
redis = "^5.2.1"
requests = "^2.32.3"
setuptools = "^75.1.0"
six = "^1.16.0"
sniffio = "^1.3.1"
soupsieve = "^2.6"
tabulate = "^0.9.0"
tqdm = "^4.66.5"
typing-inspect = "^0.9.0"
typing_extensions = "^4.12.2"
tzdata = "^2024.2"
urllib3 = "^2.2.3"
waitress = "^2.1.2"
websockets = "^13.1"
Werkzeug = "^3.0.5"
wheel = "^0.44.0"

View file

@ -1,145 +0,0 @@
from flask import Flask, request, jsonify, Response
from datetime import datetime
from functools import wraps
import os
import redis
import uuid
import json
import time
from src.graph.core import run_turn
from src.graph.tools import RAG_TOOL, CLOSE_CHAT_TOOL
from src.utils.common import common_logger, read_json_from_file
logger = common_logger
redis_client = redis.from_url(os.environ.get('REDIS_URL', 'redis://localhost:6379'))
app = Flask(__name__)
@app.route("/health", methods=["GET"])
def health():
return jsonify({"status": "ok"})
@app.route("/")
def home():
return "Hello, World!"
def require_api_key(f):
@wraps(f)
def decorated(*args, **kwargs):
auth_header = request.headers.get('Authorization')
if not auth_header or not auth_header.startswith('Bearer '):
return jsonify({'error': 'Missing or invalid authorization header'}), 401
token = auth_header.split('Bearer ')[1]
actual = os.environ.get('API_KEY', '').strip()
if actual and token != actual:
return jsonify({'error': 'Invalid API key'}), 403
return f(*args, **kwargs)
return decorated
@app.route("/chat", methods=["POST"])
@require_api_key
def chat():
logger.info('='*200)
logger.info(f"{'*'*50}Running server mode{'*'*50}")
try:
data = request.get_json()
logger.info('Complete request:')
logger.info(data)
logger.info('-'*200)
start_time = datetime.now()
config = read_json_from_file("./configs/default_config.json")
logger.info('Beginning turn')
resp_messages, resp_tokens_used, resp_state = run_turn(
messages=data.get("messages", []),
start_agent_name=data.get("startAgent", ""),
agent_configs=data.get("agents", []),
tool_configs=data.get("tools", []),
start_turn_with_start_agent=config.get("start_turn_with_start_agent", False),
state=data.get("state", {}),
additional_tool_configs=[RAG_TOOL, CLOSE_CHAT_TOOL],
complete_request=data
)
logger.info('-'*200)
logger.info('Raw output:')
logger.info((resp_messages, resp_tokens_used, resp_state))
out = {
"messages": resp_messages,
"tokens_used": resp_tokens_used,
"state": resp_state,
}
logger.info("Output:")
for k, v in out.items():
logger.info(f"{k}: {v}")
logger.info('*'*200)
logger.info('='*200)
logger.info(f"Processing time: {datetime.now() - start_time}")
return jsonify(out)
except Exception as e:
logger.error(f"Error: {e}")
return jsonify({"error": str(e)}), 500
@app.route("/chat_stream_init", methods=["POST"])
@require_api_key
def chat_stream_init():
# create a uuid for the stream
stream_id = str(uuid.uuid4())
# store the the request data in redis with 10 minute TTL
# using the key name `stream_request_<stream_id>`
# set ttl to 10 minutes
redis_client.setex(f"stream_request_{stream_id}", 600, json.dumps(request.get_json()))
return jsonify({"stream_id": stream_id})
@app.route("/chat_stream/<stream_id>", methods=["GET"])
@require_api_key
def chat_stream(stream_id):
# get the request data from redis
request_data = redis_client.get(f"stream_request_{stream_id}")
if not request_data:
return jsonify({"error": "Stream not found"}), 404
# invoke run_streamed() from agents-sdk
def generate():
# example of HTTP SSE event stream:
# https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
# --------------------------------
# id: <optional event id>
# event: <event name>
# data: {... event data ...}
#
# event: <event name>
# data: {... event data ...}
try:
yield "event: message\n"
yield "data: {\"role\": \"assistant\", \"content\": \"This is the first message!\"}\n\n" # double \n indicates end of message
time.sleep(2)
yield "event: message\n"
yield "data: {\"role\": \"assistant\", \"content\": \"This is the second message!\"}\n\n"
yield "event: done\n"
yield "data: {... state data ...}\n\n"
except Exception as e:
yield "event: error\n"
yield "data: {... error data ...}\n\n"
return Response(generate(), mimetype='text/event-stream')
if __name__ == "__main__":
print("Starting Flask server...")
from waitress import serve
serve(app, host="0.0.0.0", port=4040)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,109 @@
[tool.poetry]
name = "agents"
version = "0.1.0"
description = "RowBoat Labs Agent OS"
authors = ["Akhilesh <akhilesh@rowboatlabs.com>"]
license = "MIT"
readme = "README.md"
homepage = "https://github.com/rowboatlabs/agents"
package-mode = false
[tool.poetry.dependencies]
python = ">=3.10,<4.0"
# Dependencies
aiohttp = "^3.9.3"
annotated-types = "^0.7.0"
anyio = "^4.8.0"
asgiref = "*"
beautifulsoup4 = "^4.12.3"
blinker = "^1.9.0"
build = "1.2.2.post1"
CacheControl = "^0.14.2"
certifi = "^2024.12.14"
cffi = "^1.17.1"
charset-normalizer = "^3.4.1"
cleo = "^2.1.0"
click = "^8.1.8"
crashtest = "^0.4.1"
distlib = "^0.3.9"
distro = "^1.9.0"
dnspython = "^2.7.0"
dulwich = "^0.22.7"
et_xmlfile = "^2.0.0"
eval_type_backport = "^0.2.2"
fastjsonschema = "^2.21.1"
filelock = "^3.17.0"
firecrawl = "^1.9.0"
Flask = "^3.1.0"
gunicorn = "^23.0.0"
h11 = "^0.14.0"
httpcore = "^1.0.7"
httpx = "^0.27.2"
hypercorn = "*"
idna = "^3.10"
installer = "^0.7.0"
itsdangerous = "^2.2.0"
"jaraco.classes" = "^3.4.0"
"jaraco.context" = "^6.0.1"
"jaraco.functools" = "^4.1.0"
Jinja2 = "^3.1.5"
jiter = "^0.6.1"
jsonpath-python = "^1.0.6"
keyring = "^25.6.0"
lxml = "^5.3.0"
markdownify = "^0.13.1"
MarkupSafe = "^3.0.2"
mcp = "*"
more-itertools = "^10.6.0"
motor = "*"
msgpack = "^1.1.0"
mypy-extensions = "^1.0.0"
nest-asyncio = "^1.6.0"
numpy = "^2.2.1"
openai = "*"
openai-agents = "*"
openpyxl = "^3.1.5"
packaging = "^24.2"
pandas = "^2.2.3"
pkginfo = "^1.12.0"
platformdirs = "^4.3.6"
poetry = "^2.0.1"
poetry-core = "^2.0.1"
pycparser = "^2.22"
pydantic = "^2.10.5"
pydantic_core = "^2.27.2"
pymongo = "^4.10.1"
pyproject_hooks = "^1.2.0"
python-dateutil = "^2.9.0.post0"
python-docx = "^1.1.2"
python-dotenv = "^1.0.1"
pytz = "^2024.2"
qdrant-client = "*"
RapidFuzz = "^3.11.0"
redis = "^5.2.1"
requests = "^2.32.3"
requests-toolbelt = "^1.0.0"
setuptools = "^75.8.0"
shellingham = "^1.5.4"
six = "^1.17.0"
sniffio = "^1.3.1"
soupsieve = "^2.6"
tabulate = "^0.9.0"
tomlkit = "^0.13.2"
tqdm = "^4.67.1"
trove-classifiers = "^2025.1.15.22"
typing-inspect = "^0.9.0"
typing_extensions = "^4.12.2"
tzdata = "^2024.2"
urllib3 = "^2.3.0"
virtualenv = "^20.29.1"
waitress = "^2.1.2"
websockets = "^13.1"
Werkzeug = "^3.1.3"
wheel = "^0.44.0"
xattr = "^1.1.4"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

View file

@ -1,6 +1,7 @@
aiohttp==3.9.3
annotated-types==0.7.0
anyio==4.8.0
asgiref
beautifulsoup4==4.12.3
blinker==1.9.0
build==1.2.2.post1
@ -25,6 +26,7 @@ gunicorn==23.0.0
h11==0.14.0
httpcore==1.0.7
httpx==0.27.2
hypercorn
idna==3.10
installer==0.7.0
itsdangerous==2.2.0
@ -40,12 +42,13 @@ markdownify==0.13.1
MarkupSafe==3.0.2
mcp
more-itertools==10.6.0
motor
msgpack==1.1.0
mypy-extensions==1.0.0
nest-asyncio==1.6.0
numpy==2.2.1
openai==1.59.7
openai-agents==0.0.4
openai
openai-agents
openpyxl==3.1.5
packaging==24.2
pandas==2.2.3
@ -62,7 +65,9 @@ python-dateutil==2.9.0.post0
python-docx==1.1.2
python-dotenv==1.0.1
pytz==2024.2
qdrant-client
RapidFuzz==3.11.0
redis==5.2.1
requests==2.32.3
requests-toolbelt==1.0.0
setuptools==75.8.0
@ -83,4 +88,4 @@ waitress==2.1.2
websockets==13.1
Werkzeug==3.1.3
wheel==0.44.0
xattr==1.1.4
xattr==1.1.4

View file

@ -0,0 +1,200 @@
from flask import Flask, request, jsonify, Response
from datetime import datetime
from functools import wraps
import os
import redis
import uuid
import json
import asyncio
from hypercorn.config import Config
from hypercorn.asyncio import serve
from src.graph.core import run_turn, run_turn_streamed
from src.graph.tools import RAG_TOOL, CLOSE_CHAT_TOOL
from src.utils.common import common_logger, read_json_from_file
from pprint import pprint
logger = common_logger
redis_client = redis.from_url(os.environ.get('REDIS_URL', 'redis://localhost:6379'))
app = Flask(__name__)
@app.route("/health", methods=["GET"])
def health():
return jsonify({"status": "ok"})
@app.route("/")
def home():
return "Hello, World!"
def require_api_key(f):
@wraps(f)
def decorated(*args, **kwargs):
auth_header = request.headers.get('Authorization')
if not auth_header or not auth_header.startswith('Bearer '):
return jsonify({'error': 'Missing or invalid authorization header'}), 401
token = auth_header.split('Bearer ')[1]
actual = os.environ.get('API_KEY', '').strip()
if actual and token != actual:
return jsonify({'error': 'Invalid API key'}), 403
return f(*args, **kwargs)
return decorated
@app.route("/chat", methods=["POST"])
@require_api_key
def chat():
logger.info('='*100)
logger.info(f"{'*'*100}Running server mode{'*'*100}")
try:
data = request.get_json()
logger.info('Complete request:')
logger.info(data)
logger.info('-'*100)
start_time = datetime.now()
config = read_json_from_file("./configs/default_config.json")
logger.info('Beginning turn')
resp_messages, resp_tokens_used, resp_state = run_turn(
messages=data.get("messages", []),
start_agent_name=data.get("startAgent", ""),
agent_configs=data.get("agents", []),
tool_configs=data.get("tools", []),
start_turn_with_start_agent=config.get("start_turn_with_start_agent", False),
state=data.get("state", {}),
additional_tool_configs=[RAG_TOOL, CLOSE_CHAT_TOOL],
complete_request=data
)
logger.info('-'*100)
logger.info('Raw output:')
logger.info((resp_messages, resp_tokens_used, resp_state))
out = {
"messages": resp_messages,
"tokens_used": resp_tokens_used,
"state": resp_state,
}
logger.info("Output:")
for k, v in out.items():
logger.info(f"{k}: {v}")
logger.info('*'*100)
logger.info('='*100)
logger.info(f"Processing time: {datetime.now() - start_time}")
return jsonify(out)
except Exception as e:
logger.error(f"Error: {e}")
return jsonify({"error": str(e)}), 500
@app.route("/chat_stream_init", methods=["POST"])
@require_api_key
def chat_stream_init():
# create a uuid for the stream
stream_id = str(uuid.uuid4())
# store the request data in redis with 10 minute TTL
data = request.get_json()
redis_client.setex(f"stream_request_{stream_id}", 600, json.dumps(data))
return jsonify({"stream_id": stream_id})
@app.route("/chat_stream/<stream_id>", methods=["GET"])
@require_api_key
def chat_stream(stream_id):
# get the request data from redis
request_data = redis_client.get(f"stream_request_{stream_id}")
if not request_data:
return jsonify({"error": "Stream not found"}), 404
request_data = json.loads(request_data)
config = read_json_from_file("./configs/default_config.json")
# Preprocess messages to handle null content and role issues
for msg in request_data["messages"]:
# Handle null content in assistant messages with tool calls
if (msg.get("role") == "assistant" and
msg.get("content") is None and
msg.get("tool_calls") is not None and
len(msg.get("tool_calls")) > 0):
msg["content"] = "Calling tool"
# Handle role issues
if msg.get("role") == "tool":
msg["role"] = "developer"
elif not msg.get("role"):
msg["role"] = "user"
print('*'*200)
print("Request:")
print('*'*200)
pprint(request_data)
print('='*200)
async def process_stream():
try:
async for event_type, event_data in run_turn_streamed(
messages=request_data.get("messages", []),
start_agent_name=request_data.get("startAgent", ""),
agent_configs=request_data.get("agents", []),
tool_configs=request_data.get("tools", []),
start_turn_with_start_agent=config.get("start_turn_with_start_agent", False),
state=request_data.get("state", {}),
additional_tool_configs=[RAG_TOOL, CLOSE_CHAT_TOOL],
complete_request=request_data
):
if event_type == 'message':
print('*'*200)
print("Yielding message:")
print('*'*200)
to_yield = f"event: message\ndata: {json.dumps(event_data)}\n\n"
print(to_yield)
print('='*200)
yield to_yield
elif event_type == 'done':
print('*'*200)
print("Yielding done:")
print('*'*200)
to_yield = f"event: done\ndata: {json.dumps(event_data)}\n\n"
print(to_yield)
print('='*200)
yield to_yield
except Exception as e:
logger.error(f"Streaming error: {str(e)}")
yield f"event: error\ndata: {json.dumps({'error': str(e)})}\n\n"
def generate():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
async def get_all_chunks():
chunks = []
async for chunk in process_stream():
chunks.append(chunk)
return chunks
chunks = loop.run_until_complete(get_all_chunks())
for chunk in chunks:
yield chunk
except Exception as e:
logger.error(f"Error in generate: {e}")
raise
finally:
loop.close()
return Response(generate(), mimetype='text/event-stream')
if __name__ == "__main__":
print("Starting async server...")
config = Config()
config.bind = ["0.0.0.0:4040"]
asyncio.run(serve(app, config))

View file

@ -1,4 +1,5 @@
from copy import deepcopy
from datetime import datetime
import logging
from .helpers.access import (
@ -9,14 +10,14 @@ from .helpers.state import (
construct_state_from_response
)
from .helpers.control import get_latest_assistant_msg, get_latest_non_assistant_messages, get_last_agent_name
from .swarm_wrapper import run as swarm_run, create_response, get_agents
from .swarm_wrapper import run as swarm_run, run_streamed as swarm_run_streamed, create_response, get_agents
from src.utils.common import common_logger as logger
import asyncio
# Create a dedicated logger for swarm wrapper
logger.setLevel(logging.INFO)
print("Logger level set to INFO")
def order_messages(messages):
"""
Sorts each message's keys in a specified order and returns a new list of ordered messages.
@ -227,3 +228,140 @@ def run_turn(
tokens_used=tokens_used,
all_agents=new_agents
)
async def run_turn_streamed(
messages,
start_agent_name,
agent_configs,
tool_configs,
start_turn_with_start_agent,
state={},
additional_tool_configs=[],
complete_request={}
):
final_state = None # Initialize outside try block
try:
# Initialize agents and get external tools
new_agents = get_agents(agent_configs=agent_configs, tool_configs=tool_configs, complete_request=complete_request)
last_agent_name = get_last_agent_name(
state=state,
agent_configs=agent_configs,
start_agent_name=start_agent_name,
msg_type="user",
latest_assistant_msg=None,
start_turn_with_start_agent=start_turn_with_start_agent
)
last_new_agent = get_agent_by_name(last_agent_name, new_agents)
external_tools = get_external_tools(tool_configs)
current_agent = last_new_agent
tokens_used = {"total": 0, "prompt": 0, "completion": 0}
stream_result = await swarm_run_streamed(
agent=last_new_agent,
messages=messages,
external_tools=external_tools,
tokens_used=tokens_used
)
# Process streaming events
async for event in stream_result.stream_events():
# print('='*50)
# print("Received event: ", event)
# print('-'*50)
# Handle raw response events and accumulate tokens
if event.type == "raw_response_event":
if hasattr(event.data, 'type') and event.data.type == "response.completed":
if hasattr(event.data.response, 'usage'):
tokens_used["total"] += event.data.response.usage.total_tokens
tokens_used["prompt"] += event.data.response.usage.input_tokens
tokens_used["completion"] += event.data.response.usage.output_tokens
print('-'*50)
print(f"Found usage information. Updated cumulative tokens: {tokens_used}")
print('-'*50)
continue
# Update current agent when it changes
elif event.type == "agent_updated_stream_event":
current_agent = event.new_agent
message = {
'content': f"Agent changed to {current_agent.name}",
'role': 'assistant',
'sender': current_agent.name,
'tool_calls': None,
'tool_call_id': None,
'response_type': 'internal'
}
print("Yielding message: ", message)
yield ('message', message)
continue
# Handle run items (tools, messages, etc)
elif event.type == "run_item_stream_event":
if event.item.type == "tool_call_item":
message = {
'content': None,
'role': 'assistant',
'sender': current_agent.name if current_agent else None,
'tool_calls': [{
'function': {
'name': event.item.raw_item.name,
'arguments': event.item.raw_item.arguments
},
'id': event.item.raw_item.id,
'type': 'function'
}],
'tool_call_id': None,
'tool_name': None,
'response_type': 'internal'
}
print("Yielding message: ", message)
yield ('message', message)
elif event.item.type == "tool_call_output_item":
message = {
'content': str(event.item.output),
'role': 'tool',
'sender': None,
'tool_calls': None,
'tool_call_id': event.item.raw_item['call_id'],
'tool_name': event.item.raw_item.get('name', None),
'response_type': 'internal'
}
print("Yielding message: ", message)
yield ('message', message)
elif event.item.type == "message_output_item":
content = ""
if hasattr(event.item.raw_item, 'content'):
for content_item in event.item.raw_item.content:
if hasattr(content_item, 'text'):
content += content_item.text
message = {
'content': content,
'role': 'assistant',
'sender': current_agent.name,
'tool_calls': None,
'tool_call_id': None,
'tool_name': None,
'response_type': 'external'
}
print("Yielding message: ", message)
yield ('message', message)
print(f"\n{'='*50}\n")
# After all events are processed, set final state
final_state = {
"last_agent_name": current_agent.name if current_agent else None,
"tokens": tokens_used
}
yield ('done', {'state': final_state})
except Exception as e:
import traceback
print(traceback.format_exc())
print(f"Error in stream processing: {str(e)}")
yield ('error', {'error': str(e), 'state': final_state}) # Include final_state in error response

View file

@ -184,6 +184,7 @@ def get_agents(agent_configs, tool_configs, complete_request):
# Create Agent objects from config
for agent_config in agent_configs:
logger.debug(f"Processing config for agent: {agent_config['name']}")
print("="*100)
print(f"Processing config for agent: {agent_config['name']}")
# If hasRagSources, append the RAG tool to the agent's tools
@ -199,7 +200,6 @@ def get_agents(agent_configs, tool_configs, complete_request):
print(f"Agent {agent_config['name']} has {len(agent_config['tools'])} configured tools")
new_tools = []
print(agent_config)
rag_tool = get_rag_tool(agent_config, complete_request)
if rag_tool:
new_tools.append(rag_tool)
@ -259,6 +259,8 @@ def get_agents(agent_configs, tool_configs, complete_request):
# Look up the agent's children from the old agent and create a list called handoffs in new_agent with pointers to the children in new_agents
new_agent.handoffs = [new_agents[new_agent_name_to_index[child]] for child in new_agent_to_children[new_agent.name]]
print("Returning created agents")
print("="*100)
return new_agents
@ -341,4 +343,49 @@ def run(
logger.info(f"Completed Swarm run for agent: {agent.name}")
print(f"Completed Swarm run for agent: {agent.name}")
return response
return response
async def run_streamed(
agent,
messages,
external_tools=None,
tokens_used=None
):
"""
Wrapper function for initializing and running the Swarm client in streaming mode.
"""
logger.info(f"Initializing Swarm streaming client for agent: {agent.name}")
print(f"Initializing Swarm streaming client for agent: {agent.name}")
# Initialize default parameters
if external_tools is None:
external_tools = []
if tokens_used is None:
tokens_used = {}
# Format messages to ensure they're compatible with the OpenAI API
formatted_messages = []
for msg in messages:
if isinstance(msg, dict) and "content" in msg:
formatted_msg = {
"role": msg.get("role", "user"),
"content": msg["content"]
}
formatted_messages.append(formatted_msg)
else:
formatted_messages.append({
"role": "user",
"content": str(msg)
})
logger.info("Beginning Swarm streaming run")
print("Beginning Swarm streaming run")
try:
# Use the Runner.run_streamed method
stream_result = Runner.run_streamed(agent, formatted_messages)
return stream_result
except Exception as e:
logger.error(f"Error during streaming run: {str(e)}")
print(f"Error during streaming run: {str(e)}")
raise

View file

@ -0,0 +1,174 @@
from src.utils.common import common_logger, read_json_from_file
import requests
import json
import argparse
from datetime import datetime
logger = common_logger
logger.info("Running app_client_streaming.py")
def preprocess_messages(messages):
# Preprocess messages to handle null content and role issues
for msg in messages:
# Handle null content in assistant messages with tool calls
if (msg.get("role") == "assistant" and
msg.get("content") is None and
msg.get("tool_calls") is not None and
len(msg.get("tool_calls")) > 0):
msg["content"] = "Calling tool"
# Handle role issues
if msg.get("role") == "tool":
msg["role"] = "developer"
elif not msg.get("role"):
msg["role"] = "user"
return messages
def stream_chat(host, request_data, api_key):
start_time = datetime.now()
print("\n" + "="*80)
print(f"Starting streaming chat at {start_time}")
print(f"Host: {host}")
print("="*80 + "\n")
# First, initialize the stream
try:
print("\n" + "-"*80)
print("Initializing stream...")
init_response = requests.post(
f"{host}/chat_stream_init",
json=request_data,
headers={'Authorization': f'Bearer {api_key}'}
)
print(f"Init Response Status: {init_response.status_code}")
print(f"Init Response Text: {init_response.text}")
print("-"*80 + "\n")
if init_response.status_code != 200:
logger.error(f"Error initializing stream. Status code: {init_response.status_code}")
logger.error(f"Response: {init_response.text}")
return
init_data = init_response.json()
if 'error' in init_data:
logger.error(f"Error initializing stream: {init_data['error']}")
return
stream_id = init_data['stream_id']
print(f"Stream initialized successfully with ID: {stream_id}")
except requests.exceptions.RequestException as e:
logger.error(f"Request error during stream initialization: {e}")
return
except json.JSONDecodeError as e:
logger.error(f"Failed to decode JSON response: {e}")
logger.error(f"Raw response: {init_response.text}")
return
# Now connect to the stream
try:
print("\n" + "-"*80)
print(f"Connecting to stream {stream_id}...")
stream_response = requests.get(
f"{host}/chat_stream/{stream_id}",
headers={
'Authorization': f'Bearer {api_key}',
'Accept': 'text/event-stream'
},
stream=True
)
if stream_response.status_code != 200:
logger.error(f"Error connecting to stream. Status code: {stream_response.status_code}")
logger.error(f"Response: {stream_response.text}")
return
print(f"Successfully connected to stream")
print("-"*80 + "\n")
event_count = 0
current_data = []
try:
print("\n" + "-"*80)
print("Starting to process events...")
print("-"*80 + "\n")
for line in stream_response.iter_lines(decode_unicode=True):
if line:
if line.startswith('data: '):
data = line[6:] # Remove 'data: ' prefix
try:
event_data = json.loads(data)
event_count += 1
print("\n" + "*"*80)
print(f"Event #{event_count}")
if isinstance(event_data, dict):
# Pretty print the event data
print("Event Data:")
print(json.dumps(event_data, indent=2))
# Special handling for message events
if 'content' in event_data:
print("\nMessage Content:", event_data['content'])
if event_data.get('tool_calls'):
print("Tool Calls:", json.dumps(event_data['tool_calls'], indent=2))
else:
print("Event Data:", event_data)
print("*"*80 + "\n")
except json.JSONDecodeError as e:
print(f"Error decoding event data: {e}")
print(f"Raw data: {data}")
except Exception as e:
print(f"Error processing stream: {e}")
import traceback
traceback.print_exc()
finally:
print("\n" + "-"*80)
print(f"Closing stream after processing {event_count} events")
print("-"*80 + "\n")
stream_response.close()
except requests.exceptions.RequestException as e:
print(f"Request error during streaming: {e}")
import traceback
traceback.print_exc()
end_time = datetime.now()
duration = end_time - start_time
print("\n" + "="*80)
print(f"Streaming session completed at {end_time}")
print(f"Total duration: {duration}")
print("="*80 + "\n")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('--sample_request', type=str, required=False, default='tmp.json',
help='Sample request JSON file name under tests/sample_requests/')
parser.add_argument('--api_key', type=str, required=False, default='test',
help='API key to use for authentication')
parser.add_argument('--host', type=str, default='http://localhost:4040',
help='Host to use for the request')
args = parser.parse_args()
try:
print("\n" + "="*80)
print("Loading request data...")
request = read_json_from_file(f"./tests/sample_requests/{args.sample_request}").get("lastRequest", {})
print("Request data:")
print(json.dumps(request, indent=2))
print("Starting streaming request...")
print("="*80 + "\n")
stream_chat(args.host, request, args.api_key)
except Exception as e:
print("\n" + "!"*80)
print(f"Error in main: {e}")
import traceback
traceback.print_exc()
print("!"*80 + "\n")

View file

@ -2,12 +2,76 @@ import copy
from datetime import datetime
import json
import sys
import asyncio
from src.graph.core import run_turn, order_messages
from src.graph.core import order_messages, run_turn_streamed
from src.graph.tools import respond_to_tool_raise_error, respond_to_tool_close_chat, RAG_TOOL, CLOSE_CHAT_TOOL
from src.utils.common import common_logger, read_json_from_file
logger = common_logger
def preprocess_messages(messages):
# Preprocess messages to handle null content and role issues
for msg in messages:
# Handle null content in assistant messages with tool calls
if (msg.get("role") == "assistant" and
msg.get("content") is None and
msg.get("tool_calls") is not None and
len(msg.get("tool_calls")) > 0):
msg["content"] = "Calling tool"
# Handle role issues
if msg.get("role") == "tool":
msg["role"] = "developer"
elif not msg.get("role"):
msg["role"] = "user"
return messages
async def process_turn(messages, agent_configs, tool_configs, prompt_configs, start_agent_name, state, config, complete_request):
"""Processes a single turn using streaming API"""
print(f"\n{'*'*50}\nLatest Request:\n{'*'*50}")
request_json = {
"messages": [{k: v for k, v in msg.items() if k != 'current_turn'} for msg in messages],
"state": state,
"agents": agent_configs,
"tools": tool_configs,
"prompts": prompt_configs,
"startAgent": start_agent_name
}
print(json.dumps(request_json, indent=2))
collected_messages = []
async for event_type, event_data in run_turn_streamed(
messages=messages,
start_agent_name=start_agent_name,
agent_configs=agent_configs,
tool_configs=tool_configs,
start_turn_with_start_agent=config.get("start_turn_with_start_agent", False),
state=state,
additional_tool_configs=[RAG_TOOL, CLOSE_CHAT_TOOL],
complete_request=complete_request
):
if event_type == "message":
# Add each message to collected_messages
collected_messages.append(event_data)
elif event_type == "done":
print(f"\n\n{'*'*50}\nLatest Response:\n{'*'*50}")
response_json = {
"messages": collected_messages,
"state": event_data.get('state', {}),
}
print("Turn completed. Here are the streamed messages and final state:")
print(json.dumps(response_json, indent=2))
print('='*50)
return collected_messages, event_data.get('state', {})
elif event_type == "error":
print(f"\nError: {event_data.get('error', 'Unknown error')}")
return [], state
if __name__ == "__main__":
logger.info(f"{'*'*50}Running interactive mode{'*'*50}")
@ -16,20 +80,23 @@ if __name__ == "__main__":
tool_configs = complete_request.get("tools", [])
prompt_configs = complete_request.get("prompts", [])
start_agent_name = complete_request.get("startAgent", "")
return agent_configs, tool_configs, prompt_configs, start_agent_name
external_tool_mappings = {
"raise_error": respond_to_tool_raise_error,
"close_chat": respond_to_tool_close_chat
}
config_file = sys.argv[sys.argv.index("--config") + 1] if "--config" in sys.argv else "default_config.json"
sample_request_file = sys.argv[sys.argv.index("--sample_request") + 1] if "--sample_request" in sys.argv else "default_example.json"
print(f"Config file: {config_file}")
print(f"Sample request file: {sample_request_file}")
config = read_json_from_file(f"./configs/{config_file}")
example_request = read_json_from_file(f"./tests/sample_requests/{sample_request_file}").get("lastRequest", {})
if "--load_messages" in sys.argv:
messages = example_request.get("messages", [])
messages = order_messages(messages)
@ -57,7 +124,7 @@ if __name__ == "__main__":
agent_configs, tool_configs, prompt_configs, start_agent_name = extract_request_fields(complete_request)
print(f"\nUsing agent: {last_agent_name}")
if user_input_needed:
user_inp = input('\nUSER: ')
messages.append({
@ -71,43 +138,28 @@ if __name__ == "__main__":
break
logger.info("Added user message to conversation")
print(f"\n{'*'*50}\nLatest Request:\n{'*'*50}")
request_json = {
"messages": [{k: v for k, v in msg.items() if k != 'current_turn'} for msg in messages],
"state": state,
"agents": agent_configs,
"tools": tool_configs,
"prompts": prompt_configs,
"startAgent": start_agent_name
}
print(json.dumps(request_json, indent=2))
print(complete_request)
resp_messages, resp_tokens_used, resp_state = run_turn(
# Preprocess messages to replace role tool with role developer and add role user to empty roles
print("Preprocessing messages to replace role tool with role developer and add role user to empty roles")
messages = preprocess_messages(messages)
complete_request["messages"] = preprocess_messages(complete_request["messages"])
# Run the streaming turn
resp_messages, resp_state = asyncio.run(process_turn(
messages=messages,
start_agent_name=start_agent_name,
agent_configs=agent_configs,
tool_configs=tool_configs,
start_turn_with_start_agent=config.get("start_turn_with_start_agent", False),
prompt_configs=prompt_configs,
start_agent_name=start_agent_name,
state=state,
additional_tool_configs=[RAG_TOOL, CLOSE_CHAT_TOOL],
config=config,
complete_request=complete_request
)
))
state = resp_state
resp_messages = order_messages(resp_messages)
print(f"\n{'*'*50}\nLatest Response:\n{'*'*50}")
response_json = {
"messages": resp_messages,
"state": state,
"tokens_used": resp_tokens_used
}
print(json.dumps(response_json, indent=2))
last_msg = resp_messages[-1]
print(f"\nBOT: {last_msg}\n")
last_msg = resp_messages[-1] if resp_messages else {}
tool_calls = last_msg.get("tool_calls", [])
sender = last_msg.get("sender", "")
if config.get("return_diff_messages", True):
messages.extend(resp_messages)
else:
@ -134,7 +186,7 @@ if __name__ == "__main__":
current_tool_duration = round((datetime.now() - tool_start_time).total_seconds() * 10) / 10
logger.info(f"Tool response duration: {current_tool_duration:.1f}s")
tool_duration += current_tool_duration
if tool_name == "close_chat":
user_input_needed = False
logger.info("Closing chat")
@ -142,10 +194,12 @@ if __name__ == "__main__":
if should_break:
break
else:
user_input_needed = True
print(f"Turn Duration: {round((datetime.now() - turn_start_time).total_seconds() * 10) / 10:.1f}s\n")
print(f"Tool Response Duration: {round(tool_duration * 10) / 10:.1f}s\n")
print("Quick stats")
print(f"Turn Duration: {round((datetime.now() - turn_start_time).total_seconds() * 10) / 10:.1f}s")
print(f"Tool Response Duration: {round(tool_duration * 10) / 10:.1f}s")
print('='*50)
print("\n" + "-" * 80)

View file

@ -0,0 +1,176 @@
{
"lastRequest": {
"messages": [
{
"role": "system",
"content": ""
},
{
"role": "user",
"content": "hi"
},
{
"role": "assistant",
"sender": "Door Dash Hub",
"content": "Hello! Are you facing issues with your order items or delivery timing? How can I assist you today?",
"created_at": "2025-03-24T17:33:27.564940"
},
{
"role": "user",
"content": "my order is missing fries"
},
{
"content": "Agent changed to Door Dash Hub",
"role": "assistant",
"sender": "Door Dash Hub",
"tool_calls": null,
"tool_call_id": null,
"response_type": "internal"
},
{
"content": "Agent changed to Order Issue",
"role": "assistant",
"sender": "Order Issue",
"tool_calls": null,
"tool_call_id": null,
"response_type": "internal"
},
{
"content": "I can help with that. Could you please provide your order ID so I can check the details?",
"role": "assistant",
"sender": "Order Issue",
"tool_calls": null,
"tool_call_id": null,
"tool_name": null,
"response_type": "external"
},
{
"role": "user",
"content": "12312"
}
],
"state": {
"last_agent_name": "Order Issue",
"tokens": {
"total": 1521,
"prompt": 1486,
"completion": 35
}
},
"agents": [
{
"name": "Door Dash Hub",
"type": "conversation",
"description": "Hub agent to manage Door Dash-related queries.",
"instructions": "## \ud83e\uddd1\u200d\ud83d\udcbc Role:\nYou are responsible for directing Door Dash-related queries to appropriate agents.\n\n---\n## \u2699\ufe0f Steps to Follow:\n1. Greet the user and ask which Door Dash-related query they need help with (e.g., 'Are you facing issues with your order items or delivery timing?').\n2. If the query matches a specific task, direct the user to the corresponding agent:\n - Order Issue \u2192 [@agent:Order Issue]\n - Delayed Delivery \u2192 [@agent:Delayed Delivery]\n3. If the query doesn't match any specific task, respond with 'I'm sorry, I didn't understand. Could you clarify your request?' or escalate to human support.\n\n---\n## \ud83c\udfaf Scope:\n\u2705 In Scope:\n- Issues with order items\n- Delayed delivery issues\n\n\u274c Out of Scope:\n- Issues unrelated to Door Dash\n- General knowledge queries\n\n---\n## \ud83d\udccb Guidelines:\n\u2714\ufe0f Dos:\n- Direct queries to specific Door Dash agents promptly.\n- Call [@agent:Escalation] agent for unrecognized queries.\n\n\ud83d\udeab Don'ts:\n- Engage in detailed support.\n- Extend the conversation beyond Door Dash.\n- Provide user-facing text such as 'I will connect you now...' when calling another agent\n\n# Examples\n- **User** : I need help with my order items.\n - **Agent actions**: [@agent:Order Issue](#mention)\n\n- **User** : My delivery is delayed.\n - **Agent actions**: Call [@agent:Delayed Delivery](#mention)\n\n- **User** : I'm not sure where my order is.\n - **Agent actions**: Call [@agent:Delayed Delivery](#mention)\n\n- **User** : Can you reset my order settings?\n - **Agent actions**: [@agent:Escalation](#mention)\n\n- **User** : How are you today?\n - **Agent response**: I'm doing great. What would like help with today?",
"model": "gpt-4o-mini",
"hasRagSources": false,
"controlType": "retain",
"tools": [],
"prompts": [],
"connectedAgents": [
"Order Issue",
"Delayed Delivery",
"Escalation"
]
},
{
"name": "Post process",
"type": "post_process",
"description": "",
"instructions": "Ensure that the agent response is terse and to the point.",
"model": "gpt-4o-mini",
"hasRagSources": false,
"controlType": "retain",
"tools": [],
"prompts": [],
"connectedAgents": []
},
{
"name": "Escalation",
"type": "escalation",
"description": "",
"instructions": "Get the user's contact information and let them know that their request has been escalated.",
"model": "gpt-4o-mini",
"hasRagSources": false,
"controlType": "retain",
"tools": [],
"prompts": [],
"connectedAgents": []
},
{
"name": "Order Issue",
"type": "conversation",
"description": "Agent to assist users with missing or incorrect order items.",
"instructions": "## \ud83e\uddd1\u200d\ud83d\udcbc Role:\nAssist users with issues related to missing or incorrect order items.\n\n---\n## \u2699\ufe0f Steps to Follow:\n1. Fetch the order details using the [@tool:get_order_details] tool.\n2. Confirm the issue with the user.\n3. Provide solutions or escalate if unresolved.\n\n---\n## \ud83c\udfaf Scope:\n\u2705 In Scope:\n- Handling missing or incorrect order items\n\n\u274c Out of Scope:\n- Delayed delivery issues\n- General knowledge queries\n\n---\n## \ud83d\udccb Guidelines:\n\u2714\ufe0f Dos:\n- Ensure the user is aware of the order details before proceeding.\n\n\ud83d\udeab Don'ts:\n- Extend the conversation beyond order issues.\n\n# Examples\n- **User** : I received the wrong item in my order.\n - **Agent response**: I can help with that. Let me fetch your order details first.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My order is missing an item.\n - **Agent response**: Let's check your order details and resolve this issue.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I got someone else's order.\n - **Agent response**: I apologize for the mix-up. I'll fetch your order details to sort this out.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : Can you help me with a missing item?\n - **Agent response**: Certainly, I'll look into your order details right away.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : There's an issue with my order items.\n - **Agent response**: Let's verify your order details to address this issue.\n - **Agent actions**: Call [@tool:get_order_details](#mention)",
"model": "gpt-4o",
"hasRagSources": false,
"controlType": "retain",
"tools": [
"get_order_details"
],
"prompts": [],
"connectedAgents": []
},
{
"name": "Delayed Delivery",
"type": "conversation",
"description": "Agent to assist users with delayed delivery issues.",
"instructions": "## \ud83e\uddd1\u200d\ud83d\udcbc Role:\nAssist users with issues related to delayed delivery.\n\n---\n## \u2699\ufe0f Steps to Follow:\n1. Fetch the delivery status using the [@tool:get_delivery_status] tool.\n2. Confirm the delay with the user.\n3. Provide solutions or escalate if unresolved.\n\n---\n## \ud83c\udfaf Scope:\n\u2705 In Scope:\n- Handling delayed delivery issues\n\n\u274c Out of Scope:\n- Missing or incorrect order items\n- General knowledge queries\n\n---\n## \ud83d\udccb Guidelines:\n\u2714\ufe0f Dos:\n- Ensure the user is aware of the delivery status before proceeding.\n\n\ud83d\udeab Don'ts:\n- Extend the conversation beyond delivery issues.\n\n# Examples\n- **User** : My delivery is late.\n - **Agent response**: I can help with that. Let me fetch your delivery status first.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Where is my order? It's delayed.\n - **Agent response**: Let's check your delivery status and resolve this issue.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : My order hasn't arrived yet.\n - **Agent response**: I apologize for the delay. I'll fetch your delivery status to sort this out.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Can you help me with a delayed delivery?\n - **Agent response**: Certainly, I'll look into your delivery status right away.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : There's an issue with my delivery timing.\n - **Agent response**: Let's verify your delivery status to address this issue.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)",
"model": "gpt-4o",
"hasRagSources": false,
"controlType": "retain",
"tools": [
"get_delivery_status"
],
"prompts": [],
"connectedAgents": []
}
],
"tools": [
{
"name": "get_order_details",
"description": "Tool to fetch details about the user's order.",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The unique identifier for the order."
}
},
"required": [
"order_id"
]
},
"mockTool": true,
"mockInstructions": "Return a mock response for Door Dash order details."
},
{
"name": "get_delivery_status",
"description": "Tool to fetch the current status of the delivery.",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The unique identifier for the order."
}
},
"required": [
"order_id"
]
}
}
],
"prompts": [
{
"name": "Style prompt",
"type": "style_prompt",
"prompt": "You should be empathetic and helpful."
}
],
"startAgent": "Door Dash Hub"
}
}

View file

@ -0,0 +1,223 @@
{
"lastRequest": {
"messages": [
{
"role": "system",
"content": ""
},
{
"role": "user",
"content": "hi"
},
{
"role": "assistant",
"sender": "Door Dash Hub",
"content": "Hello! Are you facing issues with your order items or delivery timing? How can I assist you today?",
"created_at": "2025-03-24T17:33:27.564940"
},
{
"role": "user",
"content": "my order is missing fries"
},
{
"content": "Agent changed to Door Dash Hub",
"role": "assistant",
"sender": "Door Dash Hub",
"tool_calls": null,
"tool_call_id": null,
"response_type": "internal"
},
{
"content": "Agent changed to Order Issue",
"role": "assistant",
"sender": "Order Issue",
"tool_calls": null,
"tool_call_id": null,
"response_type": "internal"
},
{
"content": "Let's resolve this issue by checking your order details. Could you please provide the order ID?",
"role": "assistant",
"sender": "Order Issue",
"tool_calls": null,
"tool_call_id": null,
"tool_name": null,
"response_type": "external"
},
{
"role": "user",
"content": "123412"
},
{
"content": "Agent changed to Order Issue",
"role": "assistant",
"sender": "Order Issue",
"tool_calls": null,
"tool_call_id": null,
"response_type": "internal"
},
{
"content": null,
"role": "assistant",
"sender": "Order Issue",
"tool_calls": [
{
"function": {
"name": "get_order_details",
"arguments": "{\"order_id\":\"123412\"}"
},
"id": "fc_67e37c622f208192aceec557fbd3125609b4eca638eb3571",
"type": "function"
}
],
"tool_call_id": null,
"tool_name": null,
"response_type": "internal"
},
{
"content": "Order Details for Order ID 123412:\n\n- **Restaurant**: Luigi's Pizzeria \n- **Items Ordered**: \n - 2x Margherita Pizza \n - 1x Garlic Bread \n - 1x Caesar Salad \n- **Estimated Delivery Time**: 7:45 PM \n- **Delivery Address**: 123 Elm Street, Apt 4B \n- **Order Status**: Out for delivery \n- **Total Amount**: $32.75 \n- **Payment Method**: Credit Card (**** **** **** 5678) \n- **Contact**: (123) 456-7890 \n- **Special Instructions**: Leave at the door.",
"role": "tool",
"sender": null,
"tool_calls": null,
"tool_call_id": "call_dqCMC5oreOoS9znDDJ7PqWha",
"tool_name": null,
"response_type": "internal"
},
{
"content": "I checked your order details, and it seems the fries were not included. Could you confirm if there was an oversight in placing the order, or were they supposed to be included?",
"role": "assistant",
"sender": "Order Issue",
"tool_calls": null,
"tool_call_id": null,
"tool_name": null,
"response_type": "external"
},
{
"role": "user",
"content": "Fries were supposed to be in"
}
],
"state": {
"last_agent_name": "Order Issue",
"tokens": {
"total": 1699,
"prompt": 1643,
"completion": 56
}
},
"agents": [
{
"name": "Door Dash Hub",
"type": "conversation",
"description": "Hub agent to manage Door Dash-related queries.",
"instructions": "## \ud83e\uddd1\u200d\ud83d\udcbc Role:\nYou are responsible for directing Door Dash-related queries to appropriate agents.\n\n---\n## \u2699\ufe0f Steps to Follow:\n1. Greet the user and ask which Door Dash-related query they need help with (e.g., 'Are you facing issues with your order items or delivery timing?').\n2. If the query matches a specific task, direct the user to the corresponding agent:\n - Order Issue \u2192 [@agent:Order Issue]\n - Delayed Delivery \u2192 [@agent:Delayed Delivery]\n3. If the query doesn't match any specific task, respond with 'I'm sorry, I didn't understand. Could you clarify your request?' or escalate to human support.\n\n---\n## \ud83c\udfaf Scope:\n\u2705 In Scope:\n- Issues with order items\n- Delayed delivery issues\n\n\u274c Out of Scope:\n- Issues unrelated to Door Dash\n- General knowledge queries\n\n---\n## \ud83d\udccb Guidelines:\n\u2714\ufe0f Dos:\n- Direct queries to specific Door Dash agents promptly.\n- Call [@agent:Escalation] agent for unrecognized queries.\n\n\ud83d\udeab Don'ts:\n- Engage in detailed support.\n- Extend the conversation beyond Door Dash.\n- Provide user-facing text such as 'I will connect you now...' when calling another agent\n\n# Examples\n- **User** : I need help with my order items.\n - **Agent actions**: [@agent:Order Issue](#mention)\n\n- **User** : My delivery is delayed.\n - **Agent actions**: Call [@agent:Delayed Delivery](#mention)\n\n- **User** : I'm not sure where my order is.\n - **Agent actions**: Call [@agent:Delayed Delivery](#mention)\n\n- **User** : Can you reset my order settings?\n - **Agent actions**: [@agent:Escalation](#mention)\n\n- **User** : How are you today?\n - **Agent response**: I'm doing great. What would like help with today?",
"model": "gpt-4o-mini",
"hasRagSources": false,
"controlType": "retain",
"tools": [],
"prompts": [],
"connectedAgents": [
"Order Issue",
"Delayed Delivery",
"Escalation"
]
},
{
"name": "Post process",
"type": "post_process",
"description": "",
"instructions": "Ensure that the agent response is terse and to the point.",
"model": "gpt-4o-mini",
"hasRagSources": false,
"controlType": "retain",
"tools": [],
"prompts": [],
"connectedAgents": []
},
{
"name": "Escalation",
"type": "escalation",
"description": "",
"instructions": "Get the user's contact information and let them know that their request has been escalated.",
"model": "gpt-4o-mini",
"hasRagSources": false,
"controlType": "retain",
"tools": [],
"prompts": [],
"connectedAgents": []
},
{
"name": "Order Issue",
"type": "conversation",
"description": "Agent to assist users with missing or incorrect order items.",
"instructions": "## \ud83e\uddd1\u200d\ud83d\udcbc Role:\nAssist users with issues related to missing or incorrect order items.\n\n---\n## \u2699\ufe0f Steps to Follow:\n1. Fetch the order details using the [@tool:get_order_details] tool.\n2. Confirm the issue with the user.\n3. Provide solutions or escalate if unresolved.\n\n---\n## \ud83c\udfaf Scope:\n\u2705 In Scope:\n- Handling missing or incorrect order items\n\n\u274c Out of Scope:\n- Delayed delivery issues\n- General knowledge queries\n\n---\n## \ud83d\udccb Guidelines:\n\u2714\ufe0f Dos:\n- Ensure the user is aware of the order details before proceeding.\n\n\ud83d\udeab Don'ts:\n- Extend the conversation beyond order issues.\n\n# Examples\n- **User** : I received the wrong item in my order.\n - **Agent response**: I can help with that. Let me fetch your order details first.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My order is missing an item.\n - **Agent response**: Let's check your order details and resolve this issue.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I got someone else's order.\n - **Agent response**: I apologize for the mix-up. I'll fetch your order details to sort this out.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : Can you help me with a missing item?\n - **Agent response**: Certainly, I'll look into your order details right away.\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : There's an issue with my order items.\n - **Agent response**: Let's verify your order details to address this issue.\n - **Agent actions**: Call [@tool:get_order_details](#mention)",
"model": "gpt-4o",
"hasRagSources": false,
"controlType": "retain",
"tools": [
"get_order_details"
],
"prompts": [],
"connectedAgents": []
},
{
"name": "Delayed Delivery",
"type": "conversation",
"description": "Agent to assist users with delayed delivery issues.",
"instructions": "## \ud83e\uddd1\u200d\ud83d\udcbc Role:\nAssist users with issues related to delayed delivery.\n\n---\n## \u2699\ufe0f Steps to Follow:\n1. Fetch the delivery status using the [@tool:get_delivery_status] tool.\n2. Confirm the delay with the user.\n3. Provide solutions or escalate if unresolved.\n\n---\n## \ud83c\udfaf Scope:\n\u2705 In Scope:\n- Handling delayed delivery issues\n\n\u274c Out of Scope:\n- Missing or incorrect order items\n- General knowledge queries\n\n---\n## \ud83d\udccb Guidelines:\n\u2714\ufe0f Dos:\n- Ensure the user is aware of the delivery status before proceeding.\n\n\ud83d\udeab Don'ts:\n- Extend the conversation beyond delivery issues.\n\n# Examples\n- **User** : My delivery is late.\n - **Agent response**: I can help with that. Let me fetch your delivery status first.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Where is my order? It's delayed.\n - **Agent response**: Let's check your delivery status and resolve this issue.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : My order hasn't arrived yet.\n - **Agent response**: I apologize for the delay. I'll fetch your delivery status to sort this out.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Can you help me with a delayed delivery?\n - **Agent response**: Certainly, I'll look into your delivery status right away.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : There's an issue with my delivery timing.\n - **Agent response**: Let's verify your delivery status to address this issue.\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)",
"model": "gpt-4o",
"hasRagSources": false,
"controlType": "retain",
"tools": [
"get_delivery_status"
],
"prompts": [],
"connectedAgents": []
}
],
"tools": [
{
"name": "get_order_details",
"description": "Tool to fetch details about the user's order.",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The unique identifier for the order."
}
},
"required": [
"order_id"
]
},
"mockTool": true,
"mockInstructions": "Return a mock response for Door Dash order details."
},
{
"name": "get_delivery_status",
"description": "Tool to fetch the current status of the delivery.",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The unique identifier for the order."
}
},
"required": [
"order_id"
]
}
}
],
"prompts": [
{
"name": "Style prompt",
"type": "style_prompt",
"prompt": "You should be empathetic and helpful."
}
],
"startAgent": "Door Dash Hub"
}
}

View file

@ -0,0 +1,270 @@
{
"lastRequest": {
"projectId": "4ebd5e81-010a-4bc6-91e0-0aa98173dbac",
"messages": [
{
"content": "",
"role": "system",
"sender": null,
"tool_calls": null,
"tool_call_id": null,
"tool_name": null
},
{
"content": "Hello! How can I assist you with your DoorDash query today? Are you inquiring about a missing item, delivery status, or subscription details?",
"role": "assistant",
"sender": "DoorDash Support Hub",
"tool_calls": null,
"tool_call_id": null,
"tool_name": null,
"response_type": "internal"
},
{
"content": "Hello! How can I assist you with your DoorDash query today? Are you inquiring about a missing item, delivery status, or subscription details?",
"role": "assistant",
"sender": "DoorDash Support Hub >> External",
"tool_calls": null,
"tool_call_id": null,
"tool_name": null,
"response_type": "external"
},
{
"content": "hi",
"role": "user",
"sender": null,
"tool_calls": null,
"tool_call_id": null,
"tool_name": null
}
],
"state": {
"agent_data": [
{
"instructions": "## 🧑‍💼 Role:\nYou are responsible for directing DoorDash-related queries to appropriate agents.\n\n---\n## ⚙️ Steps to Follow:\n1. Greet the user and ask which DoorDash-related query they need help with (e.g., 'Are you inquiring about a missing item, delivery status, or subscription details?').\n2. If the query matches a specific task, direct the user to the corresponding agent:\n - Missing Items → [@agent:Missing Items]\n - Delivery Status → [@agent:Delivery Status]\n - Subscription Info → [@agent:Subscription Info]\n3. If the query doesn't match any specific task, respond with 'I'm sorry, I didn't understand. Could you clarify your request?' or escalate to human support.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Missing items queries\n- Delivery status queries\n- Subscription-related queries\n\n❌ Out of Scope:\n- Issues unrelated to DoorDash\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Direct queries to specific DoorDash agents promptly.\n- Call [@agent:Escalation] agent for unrecognized queries.\n\n🚫 Don'ts:\n- Engage in detailed support.\n- Extend the conversation beyond DoorDash.\n- Provide user-facing text such as 'I will connect you now...' when calling another agent\n\n# Examples\n- **User** : I need help with a missing item in my order.\n - **Agent actions**: Call [@agent:Missing Items](#mention)\n\n- **User** : Can you tell me the status of my delivery?\n - **Agent actions**: Call [@agent:Delivery Status](#mention)\n\n- **User** : How are you today?\n - **Agent response**: I'm doing great. What would you like help with today?\n\n- **User** : Can you reset my account settings?\n - **Agent actions**: Call [@agent:Escalation](#mention)\n\n- **User** : I have a question about my order.\n - **Agent response**: Could you specify if it's about a missing item, delivery status, or subscription details?\n\n- **User** : What are the available subscription plans?\n - **Agent actions**: Call [@agent:Subscription Info](#mention)",
"name": "DoorDash Support Hub"
},
{
"instructions": "Ensure that the agent response is terse and to the point.",
"name": "Post process"
},
{
"instructions": "Get the user's contact information and let them know that their request has been escalated.",
"name": "Escalation"
},
{
"instructions": "## 🧑‍💼 Role:\nHelp users resolve issues with missing items in their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the order details using the [@tool:get_order_details] tool.\n2. Confirm the missing items with the user.\n3. Provide resolution options or escalate if unresolved.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Resolving missing items issues\n\n❌ Out of Scope:\n- Delivery status queries\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Use [@tool:get_order_details](#mention) to fetch accurate order information.\n- Provide clear resolution options.\n\n🚫 Don'ts:\n- Assume missing items without user confirmation.\n- Extend the conversation beyond missing items.\n\n# Examples\n- **User** : I didn't receive my fries with my order.\n - **Agent response**: Let me check your order details. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My order is missing a drink.\n - **Agent response**: I apologize for the inconvenience. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get the extra sauce I ordered.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My burger is missing from the order.\n - **Agent response**: I'm sorry to hear that. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get my dessert.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)",
"name": "Missing Items"
},
{
"instructions": "## 🧑‍💼 Role:\nHelp users with queries related to the delivery status of their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the delivery status using the [@tool:get_delivery_status] tool.\n2. Provide the user with the current delivery status.\n3. Offer additional assistance if needed.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Providing delivery status updates\n\n❌ Out of Scope:\n- Resolving missing items issues\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Use [@tool:get_delivery_status](#mention) to fetch accurate delivery information.\n- Provide clear and concise status updates.\n\n🚫 Don'ts:\n- Provide status updates without fetching current information.\n- Extend the conversation beyond delivery status.\n\n# Examples\n- **User** : Where is my order?\n - **Agent response**: Let me check the delivery status for you. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order on the way?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : When will my order arrive?\n - **Agent response**: Let me find out the delivery status. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : How long until my order gets here?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order delayed?\n - **Agent response**: Let me check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)",
"name": "Delivery Status"
},
{
"instructions": "## 🧑‍💼 Role:\nProvide information and answer questions related to subscriptions using RAG.\n\n---\n## ⚙️ Steps to Follow:\n1. Use RAG to retrieve relevant information about subscriptions.\n2. Answer the user's questions based on the retrieved information.\n3. If the user's query is outside the scope of subscriptions, inform them politely.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Subscription plans and pricing\n- Subscription features and benefits\n\n❌ Out of Scope:\n- Non-subscription-related queries\n- Detailed account management\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Use RAG to provide accurate and up-to-date information.\n- Be clear and concise in your responses.\n\n🚫 Don'ts:\n- Provide information without using RAG.\n- Extend the conversation beyond subscription topics.\n\n# Examples\n- **User** : What are the available subscription plans?\n - **Agent response**: Let me check the available subscription plans for you.\n\n- **User** : How much does the premium subscription cost?\n - **Agent response**: I'll find the current pricing for the premium subscription.\n\n- **User** : Can I change my subscription plan?\n - **Agent response**: I'll provide information on how to change your subscription plan.\n\n- **User** : What benefits do I get with a subscription?\n - **Agent response**: Let me retrieve the benefits associated with our subscription plans.\n\n- **User** : Is there a free trial available?\n - **Agent response**: I'll check if there's a free trial available for our subscriptions.",
"name": "Subscription Info"
}
],
"last_agent_name": "DoorDash Support Hub"
},
"agents": [
{
"name": "DoorDash Support Hub",
"type": "conversation",
"description": "Hub agent to manage DoorDash-related queries.",
"instructions": "## 🧑‍💼 Role:\nYou are responsible for directing DoorDash-related queries to appropriate agents.\n\n---\n## ⚙️ Steps to Follow:\n1. Greet the user and ask which DoorDash-related query they need help with (e.g., 'Are you inquiring about a missing item, delivery status, or subscription details?').\n2. If the query matches a specific task, direct the user to the corresponding agent:\n - Missing Items → [@agent:Missing Items]\n - Delivery Status → [@agent:Delivery Status]\n - Subscription Info → [@agent:Subscription Info]\n3. If the query doesn't match any specific task, respond with 'I'm sorry, I didn't understand. Could you clarify your request?' or escalate to human support.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Missing items queries\n- Delivery status queries\n- Subscription-related queries\n\n❌ Out of Scope:\n- Issues unrelated to DoorDash\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Direct queries to specific DoorDash agents promptly.\n- Call [@agent:Escalation] agent for unrecognized queries.\n\n🚫 Don'ts:\n- Engage in detailed support.\n- Extend the conversation beyond DoorDash.\n- Provide user-facing text such as 'I will connect you now...' when calling another agent\n\n# Examples\n- **User** : I need help with a missing item in my order.\n - **Agent actions**: Call [@agent:Missing Items](#mention)\n\n- **User** : Can you tell me the status of my delivery?\n - **Agent actions**: Call [@agent:Delivery Status](#mention)\n\n- **User** : How are you today?\n - **Agent response**: I'm doing great. What would you like help with today?\n\n- **User** : Can you reset my account settings?\n - **Agent actions**: Call [@agent:Escalation](#mention)\n\n- **User** : I have a question about my order.\n - **Agent response**: Could you specify if it's about a missing item, delivery status, or subscription details?\n\n- **User** : What are the available subscription plans?\n - **Agent actions**: Call [@agent:Subscription Info](#mention)",
"model": "gpt-4o",
"controlType": "retain",
"ragK": 3,
"ragReturnType": "chunks",
"tools": [],
"prompts": [],
"connectedAgents": [
"Missing Items",
"Delivery Status",
"Subscription Info",
"Escalation"
]
},
{
"name": "Post process",
"type": "post_process",
"description": "",
"instructions": "Ensure that the agent response is terse and to the point.",
"model": "gpt-4o-mini",
"controlType": "retain",
"ragK": 3,
"ragReturnType": "chunks",
"tools": [],
"prompts": [],
"connectedAgents": []
},
{
"name": "Escalation",
"type": "escalation",
"description": "",
"instructions": "Get the user's contact information and let them know that their request has been escalated.",
"model": "gpt-4o-mini",
"controlType": "retain",
"ragK": 3,
"ragReturnType": "chunks",
"tools": [],
"prompts": [],
"connectedAgents": []
},
{
"name": "Missing Items",
"type": "conversation",
"description": "Agent to assist users with missing items in their orders.",
"instructions": "## 🧑‍💼 Role:\nHelp users resolve issues with missing items in their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the order details using the [@tool:get_order_details] tool.\n2. Confirm the missing items with the user.\n3. Provide resolution options or escalate if unresolved.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Resolving missing items issues\n\n❌ Out of Scope:\n- Delivery status queries\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Use [@tool:get_order_details](#mention) to fetch accurate order information.\n- Provide clear resolution options.\n\n🚫 Don'ts:\n- Assume missing items without user confirmation.\n- Extend the conversation beyond missing items.\n\n# Examples\n- **User** : I didn't receive my fries with my order.\n - **Agent response**: Let me check your order details. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My order is missing a drink.\n - **Agent response**: I apologize for the inconvenience. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get the extra sauce I ordered.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My burger is missing from the order.\n - **Agent response**: I'm sorry to hear that. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get my dessert.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)",
"model": "gpt-4o",
"controlType": "retain",
"ragK": 3,
"ragReturnType": "chunks",
"tools": [
"get_order_details"
],
"prompts": [],
"connectedAgents": []
},
{
"name": "Delivery Status",
"type": "conversation",
"description": "Agent to assist users with delivery status queries.",
"instructions": "## 🧑‍💼 Role:\nHelp users with queries related to the delivery status of their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the delivery status using the [@tool:get_delivery_status] tool.\n2. Provide the user with the current delivery status.\n3. Offer additional assistance if needed.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Providing delivery status updates\n\n❌ Out of Scope:\n- Resolving missing items issues\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Use [@tool:get_delivery_status](#mention) to fetch accurate delivery information.\n- Provide clear and concise status updates.\n\n🚫 Don'ts:\n- Provide status updates without fetching current information.\n- Extend the conversation beyond delivery status.\n\n# Examples\n- **User** : Where is my order?\n - **Agent response**: Let me check the delivery status for you. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order on the way?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : When will my order arrive?\n - **Agent response**: Let me find out the delivery status. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : How long until my order gets here?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order delayed?\n - **Agent response**: Let me check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)",
"model": "gpt-4o",
"controlType": "retain",
"ragK": 3,
"ragReturnType": "chunks",
"tools": [
"get_delivery_status"
],
"prompts": [],
"connectedAgents": []
},
{
"name": "Subscription Info",
"type": "conversation",
"description": "Agent to assist users with subscription-related queries.",
"instructions": "## 🧑‍💼 Role:\nProvide information and answer questions related to subscriptions using RAG.\n\n---\n## ⚙️ Steps to Follow:\n1. Use RAG to retrieve relevant information about subscriptions.\n2. Answer the user's questions based on the retrieved information.\n3. If the user's query is outside the scope of subscriptions, inform them politely.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Subscription plans and pricing\n- Subscription features and benefits\n\n❌ Out of Scope:\n- Non-subscription-related queries\n- Detailed account management\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Use RAG to provide accurate and up-to-date information.\n- Be clear and concise in your responses.\n\n🚫 Don'ts:\n- Provide information without using RAG.\n- Extend the conversation beyond subscription topics.\n\n# Examples\n- **User** : What are the available subscription plans?\n - **Agent response**: Let me check the available subscription plans for you.\n\n- **User** : How much does the premium subscription cost?\n - **Agent response**: I'll find the current pricing for the premium subscription.\n\n- **User** : Can I change my subscription plan?\n - **Agent response**: I'll provide information on how to change your subscription plan.\n\n- **User** : What benefits do I get with a subscription?\n - **Agent response**: Let me retrieve the benefits associated with our subscription plans.\n\n- **User** : Is there a free trial available?\n - **Agent response**: I'll check if there's a free trial available for our subscriptions.",
"model": "gpt-4o",
"controlType": "relinquish_to_parent",
"ragDataSources": [
"67e1612510540d9027909e10"
],
"ragK": 3,
"ragReturnType": "content",
"tools": [],
"prompts": [],
"connectedAgents": []
}
],
"tools": [
{
"name": "get_order_details",
"description": "Tool to fetch the user's order details.",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The unique identifier for the order."
}
},
"required": [
"order_id"
]
}
},
{
"name": "get_delivery_status",
"description": "Tool to fetch the delivery status of an order.",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The unique identifier for the order."
}
},
"required": [
"order_id"
]
},
"mockTool": true,
"mockInstructions": "Give a mock response for a door dash order delivery status."
}
],
"prompts": [
{
"name": "Style prompt",
"type": "style_prompt",
"prompt": "You should be empathetic and helpful."
},
{
"name": "Greeting",
"type": "greeting",
"prompt": "Hello! How can I help you?"
}
],
"startAgent": "DoorDash Support Hub",
"mcpServers": [
{
"name": "delivery",
"url": "http://localhost:8000/sse"
}
],
"toolWebhookUrl": "http://127.0.0.1:4020/tool_call"
},
"lastResponse": {
"messages": [
{
"content": "Hi there! How can I help you with your DoorDash query? Are you inquiring about a missing item, delivery status, or subscription details?",
"created_at": null,
"response_type": "internal",
"role": "assistant",
"sender": "DoorDash Support Hub"
},
{
"content": "Hi there! How can I help you with your DoorDash query? Are you inquiring about a missing item, delivery status, or subscription details?",
"created_at": null,
"response_type": "external",
"role": "assistant",
"sender": "DoorDash Support Hub >> External"
}
],
"state": {
"agent_data": [
{
"instructions": "## 🧑‍💼 Role:\nYou are responsible for directing DoorDash-related queries to appropriate agents.\n\n---\n## ⚙️ Steps to Follow:\n1. Greet the user and ask which DoorDash-related query they need help with (e.g., 'Are you inquiring about a missing item, delivery status, or subscription details?').\n2. If the query matches a specific task, direct the user to the corresponding agent:\n - Missing Items → [@agent:Missing Items]\n - Delivery Status → [@agent:Delivery Status]\n - Subscription Info → [@agent:Subscription Info]\n3. If the query doesn't match any specific task, respond with 'I'm sorry, I didn't understand. Could you clarify your request?' or escalate to human support.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Missing items queries\n- Delivery status queries\n- Subscription-related queries\n\n❌ Out of Scope:\n- Issues unrelated to DoorDash\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Direct queries to specific DoorDash agents promptly.\n- Call [@agent:Escalation] agent for unrecognized queries.\n\n🚫 Don'ts:\n- Engage in detailed support.\n- Extend the conversation beyond DoorDash.\n- Provide user-facing text such as 'I will connect you now...' when calling another agent\n\n# Examples\n- **User** : I need help with a missing item in my order.\n - **Agent actions**: Call [@agent:Missing Items](#mention)\n\n- **User** : Can you tell me the status of my delivery?\n - **Agent actions**: Call [@agent:Delivery Status](#mention)\n\n- **User** : How are you today?\n - **Agent response**: I'm doing great. What would you like help with today?\n\n- **User** : Can you reset my account settings?\n - **Agent actions**: Call [@agent:Escalation](#mention)\n\n- **User** : I have a question about my order.\n - **Agent response**: Could you specify if it's about a missing item, delivery status, or subscription details?\n\n- **User** : What are the available subscription plans?\n - **Agent actions**: Call [@agent:Subscription Info](#mention)",
"name": "DoorDash Support Hub"
},
{
"instructions": "Ensure that the agent response is terse and to the point.",
"name": "Post process"
},
{
"instructions": "Get the user's contact information and let them know that their request has been escalated.",
"name": "Escalation"
},
{
"instructions": "## 🧑‍💼 Role:\nHelp users resolve issues with missing items in their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the order details using the [@tool:get_order_details] tool.\n2. Confirm the missing items with the user.\n3. Provide resolution options or escalate if unresolved.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Resolving missing items issues\n\n❌ Out of Scope:\n- Delivery status queries\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Use [@tool:get_order_details](#mention) to fetch accurate order information.\n- Provide clear resolution options.\n\n🚫 Don'ts:\n- Assume missing items without user confirmation.\n- Extend the conversation beyond missing items.\n\n# Examples\n- **User** : I didn't receive my fries with my order.\n - **Agent response**: Let me check your order details. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My order is missing a drink.\n - **Agent response**: I apologize for the inconvenience. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get the extra sauce I ordered.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My burger is missing from the order.\n - **Agent response**: I'm sorry to hear that. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get my dessert.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)",
"name": "Missing Items"
},
{
"instructions": "## 🧑‍💼 Role:\nHelp users with queries related to the delivery status of their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the delivery status using the [@tool:get_delivery_status] tool.\n2. Provide the user with the current delivery status.\n3. Offer additional assistance if needed.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Providing delivery status updates\n\n❌ Out of Scope:\n- Resolving missing items issues\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Use [@tool:get_delivery_status](#mention) to fetch accurate delivery information.\n- Provide clear and concise status updates.\n\n🚫 Don'ts:\n- Provide status updates without fetching current information.\n- Extend the conversation beyond delivery status.\n\n# Examples\n- **User** : Where is my order?\n - **Agent response**: Let me check the delivery status for you. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order on the way?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : When will my order arrive?\n - **Agent response**: Let me find out the delivery status. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : How long until my order gets here?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order delayed?\n - **Agent response**: Let me check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)",
"name": "Delivery Status"
},
{
"instructions": "## 🧑‍💼 Role:\nProvide information and answer questions related to subscriptions using RAG.\n\n---\n## ⚙️ Steps to Follow:\n1. Use RAG to retrieve relevant information about subscriptions.\n2. Answer the user's questions based on the retrieved information.\n3. If the user's query is outside the scope of subscriptions, inform them politely.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Subscription plans and pricing\n- Subscription features and benefits\n\n❌ Out of Scope:\n- Non-subscription-related queries\n- Detailed account management\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Use RAG to provide accurate and up-to-date information.\n- Be clear and concise in your responses.\n\n🚫 Don'ts:\n- Provide information without using RAG.\n- Extend the conversation beyond subscription topics.\n\n# Examples\n- **User** : What are the available subscription plans?\n - **Agent response**: Let me check the available subscription plans for you.\n\n- **User** : How much does the premium subscription cost?\n - **Agent response**: I'll find the current pricing for the premium subscription.\n\n- **User** : Can I change my subscription plan?\n - **Agent response**: I'll provide information on how to change your subscription plan.\n\n- **User** : What benefits do I get with a subscription?\n - **Agent response**: Let me retrieve the benefits associated with our subscription plans.\n\n- **User** : Is there a free trial available?\n - **Agent response**: I'll check if there's a free trial available for our subscriptions.",
"name": "Subscription Info"
}
],
"last_agent_name": "DoorDash Support Hub"
},
"tokens_used": {
"completion": 50,
"prompt": 50,
"total": 100
}
}
}

View file

@ -0,0 +1,166 @@
{
"lastRequest": {
"projectId": "4ebd5e81-010a-4bc6-91e0-0aa98173dbac",
"messages": [
{
"content": "",
"role": "system",
"sender": null,
"tool_calls": null,
"tool_call_id": null,
"tool_name": null
}
],
"state": {
"last_agent_name": "DoorDash Support Hub"
},
"agents": [
{
"name": "DoorDash Support Hub",
"type": "conversation",
"description": "Hub agent to manage DoorDash-related queries.",
"instructions": "## 🧑‍💼 Role:\nYou are responsible for directing DoorDash-related queries to appropriate agents.\n\n---\n## ⚙️ Steps to Follow:\n1. Greet the user and ask which DoorDash-related query they need help with (e.g., 'Are you inquiring about a missing item, delivery status, or subscription details?').\n2. If the query matches a specific task, direct the user to the corresponding agent:\n - Missing Items → [@agent:Missing Items]\n - Delivery Status → [@agent:Delivery Status]\n - Subscription Info → [@agent:Subscription Info]\n3. If the query doesn't match any specific task, respond with 'I'm sorry, I didn't understand. Could you clarify your request?' or escalate to human support.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Missing items queries\n- Delivery status queries\n- Subscription-related queries\n\n❌ Out of Scope:\n- Issues unrelated to DoorDash\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Direct queries to specific DoorDash agents promptly.\n- Call [@agent:Escalation] agent for unrecognized queries.\n\n🚫 Don'ts:\n- Engage in detailed support.\n- Extend the conversation beyond DoorDash.\n- Provide user-facing text such as 'I will connect you now...' when calling another agent\n\n# Examples\n- **User** : I need help with a missing item in my order.\n - **Agent actions**: Call [@agent:Missing Items](#mention)\n\n- **User** : Can you tell me the status of my delivery?\n - **Agent actions**: Call [@agent:Delivery Status](#mention)\n\n- **User** : How are you today?\n - **Agent response**: I'm doing great. What would you like help with today?\n\n- **User** : Can you reset my account settings?\n - **Agent actions**: Call [@agent:Escalation](#mention)\n\n- **User** : I have a question about my order.\n - **Agent response**: Could you specify if it's about a missing item, delivery status, or subscription details?\n\n- **User** : What are the available subscription plans?\n - **Agent actions**: Call [@agent:Subscription Info](#mention)",
"model": "gpt-4o",
"controlType": "retain",
"ragK": 3,
"ragReturnType": "chunks",
"tools": [],
"prompts": [],
"connectedAgents": [
"Missing Items",
"Delivery Status",
"Subscription Info",
"Escalation"
]
},
{
"name": "Post process",
"type": "post_process",
"description": "",
"instructions": "Ensure that the agent response is terse and to the point.",
"model": "gpt-4o-mini",
"controlType": "retain",
"ragK": 3,
"ragReturnType": "chunks",
"tools": [],
"prompts": [],
"connectedAgents": []
},
{
"name": "Escalation",
"type": "escalation",
"description": "",
"instructions": "Get the user's contact information and let them know that their request has been escalated.",
"model": "gpt-4o-mini",
"controlType": "retain",
"ragK": 3,
"ragReturnType": "chunks",
"tools": [],
"prompts": [],
"connectedAgents": []
},
{
"name": "Missing Items",
"type": "conversation",
"description": "Agent to assist users with missing items in their orders.",
"instructions": "## 🧑‍💼 Role:\nHelp users resolve issues with missing items in their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the order details using the [@tool:get_order_details] tool.\n2. Confirm the missing items with the user.\n3. Provide resolution options or escalate if unresolved.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Resolving missing items issues\n\n❌ Out of Scope:\n- Delivery status queries\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Use [@tool:get_order_details](#mention) to fetch accurate order information.\n- Provide clear resolution options.\n\n🚫 Don'ts:\n- Assume missing items without user confirmation.\n- Extend the conversation beyond missing items.\n\n# Examples\n- **User** : I didn't receive my fries with my order.\n - **Agent response**: Let me check your order details. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My order is missing a drink.\n - **Agent response**: I apologize for the inconvenience. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get the extra sauce I ordered.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : My burger is missing from the order.\n - **Agent response**: I'm sorry to hear that. Let's verify your order details. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)\n\n- **User** : I didn't get my dessert.\n - **Agent response**: Let's check your order details to confirm. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_order_details](#mention)",
"model": "gpt-4o",
"controlType": "retain",
"ragK": 3,
"ragReturnType": "chunks",
"tools": [
"get_order_details"
],
"prompts": [],
"connectedAgents": []
},
{
"name": "Delivery Status",
"type": "conversation",
"description": "Agent to assist users with delivery status queries.",
"instructions": "## 🧑‍💼 Role:\nHelp users with queries related to the delivery status of their orders.\n\n---\n## ⚙️ Steps to Follow:\n1. Fetch the delivery status using the [@tool:get_delivery_status] tool.\n2. Provide the user with the current delivery status.\n3. Offer additional assistance if needed.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Providing delivery status updates\n\n❌ Out of Scope:\n- Resolving missing items issues\n- General knowledge queries\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Use [@tool:get_delivery_status](#mention) to fetch accurate delivery information.\n- Provide clear and concise status updates.\n\n🚫 Don'ts:\n- Provide status updates without fetching current information.\n- Extend the conversation beyond delivery status.\n\n# Examples\n- **User** : Where is my order?\n - **Agent response**: Let me check the delivery status for you. Could you please provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order on the way?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : When will my order arrive?\n - **Agent response**: Let me find out the delivery status. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : How long until my order gets here?\n - **Agent response**: I'll check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)\n\n- **User** : Is my order delayed?\n - **Agent response**: Let me check the delivery status for you. Could you provide your order ID?\n - **Agent actions**: Call [@tool:get_delivery_status](#mention)",
"model": "gpt-4o",
"controlType": "retain",
"ragK": 3,
"ragReturnType": "chunks",
"tools": [
"get_delivery_status"
],
"prompts": [],
"connectedAgents": []
},
{
"name": "Subscription Info",
"type": "conversation",
"description": "Agent to assist users with subscription-related queries.",
"instructions": "## 🧑‍💼 Role:\nProvide information and answer questions related to subscriptions using RAG.\n\n---\n## ⚙️ Steps to Follow:\n1. Use RAG to retrieve relevant information about subscriptions.\n2. Answer the user's questions based on the retrieved information.\n3. If the user's query is outside the scope of subscriptions, inform them politely.\n\n---\n## 🎯 Scope:\n✅ In Scope:\n- Subscription plans and pricing\n- Subscription features and benefits\n\n❌ Out of Scope:\n- Non-subscription-related queries\n- Detailed account management\n\n---\n## 📋 Guidelines:\n✔ Dos:\n- Use RAG to provide accurate and up-to-date information.\n- Be clear and concise in your responses.\n\n🚫 Don'ts:\n- Provide information without using RAG.\n- Extend the conversation beyond subscription topics.\n\n# Examples\n- **User** : What are the available subscription plans?\n - **Agent response**: Let me check the available subscription plans for you.\n\n- **User** : How much does the premium subscription cost?\n - **Agent response**: I'll find the current pricing for the premium subscription.\n\n- **User** : Can I change my subscription plan?\n - **Agent response**: I'll provide information on how to change your subscription plan.\n\n- **User** : What benefits do I get with a subscription?\n - **Agent response**: Let me retrieve the benefits associated with our subscription plans.\n\n- **User** : Is there a free trial available?\n - **Agent response**: I'll check if there's a free trial available for our subscriptions.",
"model": "gpt-4o",
"controlType": "relinquish_to_parent",
"ragDataSources": [
"67e1612510540d9027909e10"
],
"ragK": 3,
"ragReturnType": "content",
"tools": [],
"prompts": [],
"connectedAgents": []
}
],
"tools": [
{
"name": "get_order_details",
"description": "Tool to fetch the user's order details.",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The unique identifier for the order."
}
},
"required": [
"order_id"
]
}
},
{
"name": "get_delivery_status",
"description": "Tool to fetch the delivery status of an order.",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The unique identifier for the order."
}
},
"required": [
"order_id"
]
},
"mockTool": true,
"mockInstructions": "Give a mock response for a door dash order delivery status."
}
],
"prompts": [
{
"name": "Style prompt",
"type": "style_prompt",
"prompt": "You should be empathetic and helpful."
},
{
"name": "Greeting",
"type": "greeting",
"prompt": "Hello! How can I help you?"
}
],
"startAgent": "DoorDash Support Hub",
"mcpServers": [
{
"name": "delivery",
"url": "http://localhost:8000/sse"
}
],
"toolWebhookUrl": "http://127.0.0.1:4020/tool_call"
}
}

View file

@ -15,7 +15,7 @@ services:
- AUTH0_ISSUER_BASE_URL=${AUTH0_ISSUER_BASE_URL}
- AUTH0_CLIENT_ID=${AUTH0_CLIENT_ID}
- AUTH0_CLIENT_SECRET=${AUTH0_CLIENT_SECRET}
- AGENTS_API_URL=http://agents:3001
- AGENTS_API_URL=http://rowboat_agents:3001
- AGENTS_API_KEY=${AGENTS_API_KEY}
- COPILOT_API_URL=http://copilot:3002
- COPILOT_API_KEY=${COPILOT_API_KEY}
@ -37,9 +37,9 @@ services:
- MAX_PROJECTS_PER_USER=${MAX_PROJECTS_PER_USER}
restart: unless-stopped
agents:
rowboat_agents:
build:
context: ./apps/agents
context: ./apps/rowboat_agents
dockerfile: Dockerfile
ports:
- "3001:3001"