Skip to content

Commit 2307d1b

Browse files
vvillait88claude
andcommitted
fix(commerce): default warnings + recommended_tools adapt to rails in how_to_pay (parity with node)
Mirror of node-commerce 39bdf35. build_agent_instructions previously emitted the full warning + tool list regardless of which rails the merchant accepts. Now defaults are derived from rails declared in how_to_pay: - tempo present → tempo warning + tempo CLI tool - x402_base or x402_solana present → x402 warning + agentscore-pay tool - stripe-only → empty warnings + empty rail-specific tools Adds test_build_agent_instructions_warnings_match_rails covering x402-only, tempo-only, stripe-only configurations. 483 → 485 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent f780358 commit 2307d1b

2 files changed

Lines changed: 64 additions & 22 deletions

File tree

‎agentscore_commerce/challenge/agent_instructions.py‎

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,47 @@
33
from dataclasses import dataclass, field
44
from typing import Any
55

6-
DEFAULT_RECOMMENDED_TOOLS = [
7-
"`tempo request` for Tempo USDC (installs via `tempo add request`)",
8-
(
9-
"`agentscore-pay` (npm: `@agent-score/pay`) — single CLI for x402 on Base + Solana, "
10-
"also speaks tempo MPP via `--chain tempo`"
11-
),
12-
]
6+
_TEMPO_WARNING = (
7+
"Do NOT use `tempo wallet transfer` to pay to the address above. That moves USDC on-chain but does not "
8+
"notify this server, leaving your order in pending_identity state. Use `tempo request` instead — it performs "
9+
"the full MPP handshake (signs, submits Authorization: Payment, waits for server confirmation)."
10+
)
11+
_X402_WARNING = (
12+
"Do NOT send USDC manually to the x402 deposit addresses (e.g. via a bare wallet `transfer`). Use "
13+
"`agentscore-pay pay` so the X-Payment credential is signed and submitted; otherwise the order stays in "
14+
"pending_identity even though the deposit lands."
15+
)
16+
_TEMPO_TOOL = "`tempo request` for Tempo USDC (installs via `tempo add request`)"
17+
_AGENTSCORE_PAY_TOOL = (
18+
"`agentscore-pay` (npm: `@agent-score/pay`) — single CLI for x402 on Base + Solana, "
19+
"also speaks tempo MPP via `--chain tempo`"
20+
)
21+
1322
DEFAULT_WALLET_COMPATIBILITY = (
1423
"No specific wallet stack required. The 402 challenge is rail-neutral: any client that can produce a valid "
1524
"MPP credential (Authorization: Payment) or x402 X-Payment header is accepted. The CLI commands above are "
1625
"the easiest path; sign-it-yourself is fine too."
1726
)
18-
DEFAULT_WARNINGS = [
19-
(
20-
"Do NOT use `tempo wallet transfer` to pay to the address above. That moves USDC on-chain but does not "
21-
"notify this server, leaving your order in pending_identity state. Use `tempo request` instead — it performs "
22-
"the full MPP handshake (signs, submits Authorization: Payment, waits for server confirmation)."
23-
),
24-
(
25-
"Do NOT send USDC manually to the x402 deposit addresses (e.g. via a bare wallet `transfer`). Use "
26-
"`agentscore-pay pay` so the X-Payment credential is signed and submitted; otherwise the order stays in "
27-
"pending_identity even though the deposit lands."
28-
),
29-
]
27+
28+
29+
def _default_recommended_tools(how_to_pay: dict[str, Any]) -> list[str]:
30+
tools: list[str] = []
31+
has_tempo = "tempo" in how_to_pay
32+
has_x402 = "x402_base" in how_to_pay or "x402_solana" in how_to_pay
33+
if has_tempo:
34+
tools.append(_TEMPO_TOOL)
35+
if has_tempo or has_x402:
36+
tools.append(_AGENTSCORE_PAY_TOOL)
37+
return tools
38+
39+
40+
def _default_warnings(how_to_pay: dict[str, Any]) -> list[str]:
41+
w: list[str] = []
42+
if "tempo" in how_to_pay:
43+
w.append(_TEMPO_WARNING)
44+
if "x402_base" in how_to_pay or "x402_solana" in how_to_pay:
45+
w.append(_X402_WARNING)
46+
return w
3047

3148

3249
@dataclass
@@ -41,13 +58,22 @@ class BuildAgentInstructionsInput:
4158

4259

4360
def build_agent_instructions(input: BuildAgentInstructionsInput) -> dict[str, Any]:
44-
"""Build the agent_instructions block — combines how_to_pay with tools, warnings, compat note, timeout."""
61+
"""Build the agent_instructions block — combines how_to_pay with tools, warnings, compat note, timeout.
62+
63+
Defaults adapt to the rails declared in ``how_to_pay``: only tempo-relevant warnings/tools
64+
appear if ``how_to_pay["tempo"]`` is set, only x402-relevant ones if ``x402_base``/
65+
``x402_solana`` are set. Vendors override ``warnings``/``recommended_tools`` for full control.
66+
"""
67+
recommended_tools = (
68+
input.recommended_tools if input.recommended_tools is not None else _default_recommended_tools(input.how_to_pay)
69+
)
70+
warnings = input.warnings if input.warnings is not None else _default_warnings(input.how_to_pay)
4571
out: dict[str, Any] = {
4672
"how_to_pay": input.how_to_pay,
47-
"recommended_tools": input.recommended_tools or DEFAULT_RECOMMENDED_TOOLS,
73+
"recommended_tools": recommended_tools,
4874
"wallet_compatibility": input.wallet_compatibility or DEFAULT_WALLET_COMPATIBILITY,
4975
"timeout_seconds": input.timeout_seconds,
50-
"warnings": input.warnings if input.warnings is not None else DEFAULT_WARNINGS,
76+
"warnings": warnings,
5177
}
5278
if input.recommended:
5379
out["recommended"] = input.recommended

‎tests/test_challenge.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,22 @@ def test_build_agent_instructions_uses_defaults():
115115
assert any("tempo wallet transfer" in w for w in out["warnings"])
116116

117117

118+
def test_build_agent_instructions_warnings_match_rails():
119+
"""Defaults adapt to which rails are present in how_to_pay."""
120+
x402_only = build_agent_instructions(BuildAgentInstructionsInput(how_to_pay={"x402_base": {}}))
121+
assert not any("tempo wallet transfer" in w for w in x402_only["warnings"])
122+
assert any("x402 deposit addresses" in w for w in x402_only["warnings"])
123+
assert not any("tempo request" in t for t in x402_only["recommended_tools"])
124+
assert any("agentscore-pay" in t for t in x402_only["recommended_tools"])
125+
126+
tempo_only = build_agent_instructions(BuildAgentInstructionsInput(how_to_pay={"tempo": {}}))
127+
assert not any("x402 deposit addresses" in w for w in tempo_only["warnings"])
128+
129+
stripe_only = build_agent_instructions(BuildAgentInstructionsInput(how_to_pay={"stripe": {}}))
130+
assert stripe_only["warnings"] == []
131+
assert stripe_only["recommended_tools"] == []
132+
133+
118134
def test_build_402_body_assembles_full_response():
119135
body = build_402_body(
120136
Build402BodyInput(

0 commit comments

Comments
 (0)