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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions a2a/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,12 @@ The Chat Client UCP Profile can be found at http://localhost:3000/profile/agent-
2. Type `"show me cookies available in stock"` and press enter
3. The agent will return products available in stock
4. Click **"Add to Checkout"** for any product
5. The agent will ask for required information such as email address, shipping address, etc.
6. Once the required information is provided, click **"Complete Payment"**
7. The UI shows available mock payment options
8. Select a payment method and click **"Confirm Purchase"**
9. The agent will create an order and return the order confirmation
5. [Optional] Type `"apply discount code 10OFF"` to get a 10% discount
6. The agent will ask for required information such as email address, shipping address, etc.
7. Once the required information is provided, click **"Complete Payment"**
8. The UI shows available mock payment options
9. Select a payment method and click **"Confirm Purchase"**
10. The agent will create an order and return the order confirmation

</td>
</tr>
Expand Down
30 changes: 29 additions & 1 deletion a2a/business_agent/src/business_agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,32 @@ def get_checkout(tool_context: ToolContext) -> dict:
}


def apply_discount_code(tool_context: ToolContext, discount_code: str) -> dict:
"""Apply a discount code to the checkout.

Args:
tool_context: The tool context for the current request.
discount_code: The discount code to apply.

Returns:
dict: Returns the response from the tool with success or error status.

"""
checkout_id = _get_current_checkout_id(tool_context)

if not checkout_id:
return _create_error_response("A Checkout has not yet been created.")

if store.apply_discount(checkout_id, discount_code):
checkout = store.get_checkout(checkout_id)
return {
UCP_CHECKOUT_KEY: checkout.model_dump(mode="json"),
"status": "success",
}
else:
return _create_error_response("Invalid discount code.")


def update_customer_details(
tool_context: ToolContext,
first_name: str,
Expand Down Expand Up @@ -450,7 +476,8 @@ def modify_output_after_agent(
" search for the products and then add the matching products to"
" checkout session.If the user asks to replace products,"
" use remove_from_checkout and add_to_checkout tools to replace the"
" products to match the user request"
" products to match the user request. If the user provides a discount"
" code, apply it to the checkout."
),
tools=[
search_shopping_catalog,
Expand All @@ -461,6 +488,7 @@ def modify_output_after_agent(
start_payment,
update_customer_details,
complete_checkout,
apply_discount_code,
],
after_tool_callback=after_tool_modifier,
after_agent_callback=modify_output_after_agent,
Expand Down
12 changes: 12 additions & 0 deletions a2a/business_agent/src/business_agent/data/agent_card.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@
"tags": [
"checkout"
]
},
{
"description": "Applies a discount to the current checkout session",
"examples": [
"Apply discount code 10OFF"
],
"id": "apply_discount",
"name": "Apply Discount",
"tags": [
"checkout",
"discount"
]
}
],
"url": "http://localhost:10999",
Expand Down
7 changes: 7 additions & 0 deletions a2a/business_agent/src/business_agent/data/ucp.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
"spec": "https://ucp.dev/specs/shopping/fulfillment",
"schema": "https://ucp.dev/schemas/shopping/fulfillment.json",
"extends": "dev.ucp.shopping.checkout"
},
{
"name": "dev.ucp.shopping.discount",
"version": "2026-01-11",
"spec": "https://ucp.dev/specs/shopping/discount",
"schema": "https://ucp.dev/schemas/shopping/discount.json",
"extends": "dev.ucp.shopping.discount"
}
]
},
Expand Down
26 changes: 26 additions & 0 deletions a2a/business_agent/src/business_agent/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def __init__(self):
self._products = {}
self._checkouts = {}
self._orders = {}
self._discounts = {}
self._initialize_ucp_metadata()
self._initialize_products()

Expand Down Expand Up @@ -349,6 +350,9 @@ def _recalculate_checkout(self, checkout: Checkout) -> None:

subtotal = items_base_amount - items_discount
discount = 0
if checkout.id in self._discounts:
discount_percentage = self._discounts[checkout.id]
discount = int(subtotal * discount_percentage / 100)

totals = [
Total(
Expand Down Expand Up @@ -484,6 +488,9 @@ def start_payment(self, checkout_id: str) -> Checkout | str:
if (
isinstance(checkout, FulfillmentCheckout)
and checkout.fulfillment is None
) and not any(
line_item.item.id == "donation"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unintentional change?

for line_item in checkout.line_items
):
messages.append("Provide a fulfillment address")

Expand Down Expand Up @@ -557,3 +564,22 @@ def _get_fulfillment_options(self) -> list[FulfillmentOptionResponse]:
],
),
]

def apply_discount(self, checkout_id: str, discount_code: str) -> bool:
"""Apply a discount to the checkout.

Args:
checkout_id (str): ID of the checkout to apply the discount to.
discount_code (str): The discount code to apply.

Returns:
bool: True if the discount was applied, False otherwise.

"""
if discount_code == "10OFF":
self._discounts[checkout_id] = 10
checkout = self.get_checkout(checkout_id)
if checkout:
self._recalculate_checkout(checkout)
return True
return False