Skip to content

Commit 08ee3bc

Browse files
authored
Merge pull request #247 from microsoft/james-dev-agentic-ai
fix prompt and bug and logistic a2a server
2 parents 030f58f + 33d83a1 commit 08ee3bc

File tree

5 files changed

+52
-41
lines changed

5 files changed

+52
-41
lines changed

agentic_ai/agents/semantic_kernel/multi_agent/a2a/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ sequenceDiagram
3232
LogAgent-->>CSAgent: PickupScheduledConfirmation (confirmation details)
3333
CSAgent->>Customer: Confirms pickup details, provides instructions
3434
```
35+
3536
## Running the A2A Demo End-to-End
3637

3738
The repo ships three Python modules:
Binary file not shown.

agentic_ai/agents/semantic_kernel/multi_agent/a2a/logistic_a2a_server.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,10 @@ async def build_sk_logistics_agent() -> ChatCompletionAgent:
7070
"You are the Logistics AI agent responsible for arranging product-return "
7171
"pick-ups."
7272
"Supported request types:\n"
73-
" • availability_request\n"
74-
" • schedule_pickup\n"
75-
" • cancel_request\n"
73+
" • availability_request: requireing pickup address and preferred data range\n"
74+
" • schedule_pickup: need order_id, address and timeslot\n"
75+
" • cancel_request\n." \
76+
7677
)
7778

7879
agent = ChatCompletionAgent(
@@ -113,11 +114,11 @@ async def execute( # type: ignore[override]
113114
try:
114115
agent = await self._get_agent()
115116
query = context.get_user_input()
117+
print(f"Received query: {query}")
116118
task = context.current_task
117119
if not task:
118120
task = new_task(context.message)
119121
await event_queue.enqueue_event(task)
120-
print("received contextid", task.contextId)
121122
#get thread from session store
122123
thread = AGENT_STATE_STORE.get(task.contextId, {})
123124
# Retrieve user's raw JSON payload (1st text part)
@@ -128,6 +129,7 @@ async def execute( # type: ignore[override]
128129
else:
129130
response = await agent.get_response(messages=query)
130131
response_content = str(response.content)
132+
print(f"Response content: {response_content}")
131133
# Update the thread in the session store
132134
AGENT_STATE_STORE[task.contextId] = response.thread if response.thread else {}
133135

agentic_ai/agents/semantic_kernel/multi_agent/a2a/logistic_mcp.py

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from dotenv import load_dotenv
1111
from fastmcp import FastMCP
1212
from pydantic import BaseModel, Field, field_validator
13+
import logging
1314

1415
# ──────────────────── FastMCP initialisation ────────────────────────
1516
mcp = FastMCP(
@@ -61,11 +62,8 @@ class PickupAvailabilityRequest(BaseModel):
6162
"""
6263

6364
address: str = Field(..., description="Street address for the return pick-up")
64-
earliest_date: Optional[str] = Field(
65-
None, description="First acceptable date (YYYY-MM-DD, default: tomorrow)"
66-
)
67-
latest_date: Optional[str] = Field(
68-
None, description="Last acceptable date (YYYY-MM-DD, default: +7 days)"
65+
earliest_date: str = Field( description="First acceptable date (YYYY-MM-DD)")
66+
latest_date: Optional[str] = Field( description="Last acceptable date (YYYY-MM-DD)"
6967
)
7068
count: Optional[int] = Field(
7169
5, description="How many candidate slots to return (max 10)"
@@ -138,6 +136,7 @@ def get_pickup_availability(
138136
requested interval we expose three windows – 09-12, 12-15, 15-18 –
139137
until we have satisfied `count` slots.
140138
"""
139+
print(f"Received availability request: {params}") # Debug output
141140
carriers = ["UPS", "FedEx", "DHL"] # round-robin assignment
142141

143142
start = datetime.strptime(params.earliest_date, "%Y-%m-%d")
@@ -161,7 +160,8 @@ def get_pickup_availability(
161160
carrier=carriers[len(slots) % len(carriers)],
162161
)
163162
)
164-
day_cursor += timedelta(days=1)
163+
day_cursor += timedelta(days=1)
164+
logging.debug("Generated slots: %s", slots) # Debug output
165165

166166
return PickupAvailabilityResponse(slots=slots)
167167

@@ -170,27 +170,31 @@ def schedule_pickup(
170170
request: PickupConfirmationRequest,
171171
) -> PickupScheduledConfirmation:
172172
db = get_db()
173-
cur = db.execute(
174-
"""
175-
INSERT INTO Pickups(order_id, slot_id, date, start_time, end_time,
176-
carrier, address, status, created_at)
177-
VALUES (?,?,?,?,?,?,?,?,?)
178-
""",
179-
(
180-
request.order_id,
181-
request.slot.slot_id,
182-
request.slot.date,
183-
request.slot.start_time,
184-
request.slot.end_time,
185-
request.slot.carrier,
186-
request.address,
187-
"scheduled",
188-
datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
189-
),
190-
)
191-
pickup_id = cur.lastrowid
192-
db.commit()
193-
db.close()
173+
try:
174+
cur = db.execute(
175+
"""
176+
INSERT INTO Pickups(order_id, slot_id, date, start_time, end_time,
177+
carrier, address, status, created_at)
178+
VALUES (?,?,?,?,?,?,?,?,?)
179+
""",
180+
(
181+
request.order_id,
182+
request.slot.slot_id,
183+
request.slot.date,
184+
request.slot.start_time,
185+
request.slot.end_time,
186+
request.slot.carrier,
187+
request.address,
188+
"scheduled",
189+
datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
190+
),
191+
)
192+
pickup_id = cur.lastrowid
193+
db.commit()
194+
db.close()
195+
except sqlite3.Error as e:
196+
logging.error(f"Database error: {e}") # Log database errors
197+
194198

195199
return PickupScheduledConfirmation(
196200
pickup_id=pickup_id,

agentic_ai/agents/semantic_kernel/multi_agent/a2a/multi_agent_a2a.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,15 @@ async def _ensure_client(self) -> None:
6060

6161
# -------- the single exposed tool -------------------------------
6262
@kernel_function(
63-
name="logistics_chat",
63+
name="logistics_agent",
6464
description=(
65-
"Talk to Contoso Logistics to set up a return pick-up. "
66-
"Just pass the user's message; the agent will respond with the next step."
67-
),
65+
"Logistics AI agent responsible for arranging product-return "
66+
"pick-ups."
67+
"Supported request types:\n"
68+
" • availability_request\n"
69+
" • schedule_pickup\n"
70+
" • cancel_request\n"
71+
),
6872
)
6973
async def chat(self, message: str) -> str:
7074
"""
@@ -105,7 +109,7 @@ def __init__(self, state_store, session_id) -> None:
105109

106110
# URLs / env ---------------------------------------------------
107111
self.logistics_a2a_url = os.getenv("LOGISTICS_A2A_URL", "http://localhost:9100")
108-
self.mcp_server_uri = os.getenv("LOGISTIC_MCP_SERVER_URI")
112+
self.mcp_server_uri = os.getenv("MCP_SERVER_URI")
109113

110114
# runtime members ---------------------------------------------
111115
self._initialized = False
@@ -142,11 +146,9 @@ async def _setup_agents(self) -> None:
142146
self.customer_service_agent = ChatCompletionAgent(
143147
service=AzureChatCompletion(),
144148
name="customer_service_agent",
145-
instructions=(
146-
"You are a helpful Contoso customer-service assistant.\n"
147-
"• Use Contoso MCP tools for order & billing.\n"
148-
"• For product returns, talk to the 'logistics_chat' tool "
149-
"to arrange pick-ups – you can speak naturally, no JSON needed."
149+
instructions=( "You are a helpful assistant. You can use multiple tools to find information and answer questions. "
150+
"When customer ask for a product return, first check if the product is eligible for return, that is if the order has been delivered and check with customer if the condition of the product is acceptable and the return is within 30 days of delivery. "
151+
"If the product is eligible for return, ask customer for their address, their prefered timeframe and forward all information to the logistic agent to schedule a pick-up. Ask logistic agent for 3 options within the next week. "
150152
),
151153
plugins=[
152154
contoso_plugin,
@@ -167,11 +169,13 @@ async def _setup_agents(self) -> None:
167169
# ----------------------------------------------------------------
168170
async def chat_async(self, prompt: str) -> str:
169171
await self._setup_agents()
172+
logging.info("prompt: %s", prompt)
170173

171174
response = await self.customer_service_agent.get_response(
172175
messages=prompt, thread=self._thread
173176
)
174177
response_content = str(response.content)
178+
logging.info("response: %s", response_content)
175179

176180
# ---------- persist state ------------------------------------
177181
self._thread = response.thread

0 commit comments

Comments
 (0)