What you'll build
A Python agent where Claude has a get_apex_signal tool. When you ask it something like "is now a reasonable time to add to BTC?", the model pulls the regime and sentiment signals itself, reads them, and responds with reasoning grounded in current data rather than its training cutoff. Each signal call is a tiny x402 payment from a wallet your code controls.
Prerequisites
- An Anthropic API key (
ANTHROPIC_API_KEY). - A burner wallet with a few dollars of USDC on Base, plus a little ETH for gas. See the x402 quickstart if this is new.
- Python 3.10+.
pip install anthropic x402 eth-account requests
The integration, end to end
There are two clients: one that pays APEX, and one that talks to Claude. The tool definition tells Claude what signals exist and when to reach for them; the tool-use loop runs the paid call and feeds the result back.
import os, json
from anthropic import Anthropic
from x402.clients.requests import x402_requests
from eth_account import Account
# --- Client that pays APEX signal calls over x402 ---
account = Account.from_key(os.environ["EVM_PRIVATE_KEY"])
apex = x402_requests(account)
def call_apex(signal: str) -> dict:
url = f"https://apexrunner.ai/signals/{signal}"
return apex.get(url).json()
# --- Client that talks to Claude ---
claude = Anthropic() # reads ANTHROPIC_API_KEY
TOOLS = [{
"name": "get_apex_signal",
"description": (
"Fetch a live crypto market signal from APEX Runner. "
"regime-confluence = market regime (trending/ranging/crisis); "
"fear-greed = sentiment 0-100; "
"crowded-trade-detector = crowding / reversal risk; "
"dca-reentry-gate = whether a DCA add is gated open. "
"Each call costs a small USDC micropayment, so call only what you need."
),
"input_schema": {
"type": "object",
"properties": {
"signal": {
"type": "string",
"description": "Signal slug, e.g. 'regime-confluence', 'fear-greed'."
}
},
"required": ["signal"]
}
}]
def run(prompt: str) -> str:
messages = [{"role": "user", "content": prompt}]
while True:
resp = claude.messages.create(
model="claude-sonnet-4-6", # use the latest Sonnet; check docs.claude.com
max_tokens=1024,
tools=TOOLS,
messages=messages,
)
if resp.stop_reason != "tool_use":
return "".join(b.text for b in resp.content if b.type == "text")
# keep the assistant's tool-use turn in the transcript
messages.append({"role": "assistant", "content": resp.content})
# run each requested signal and return the results
results = []
for block in resp.content:
if block.type == "tool_use" and block.name == "get_apex_signal":
data = call_apex(block.input["signal"])
results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(data),
})
messages.append({"role": "user", "content": results})
print(run(
"Is now a reasonable time to add to a BTC position? "
"Check the market regime and sentiment before you answer."
))
That's the whole integration. Claude sees the tool, decides whether the question needs live data, calls get_apex_signal one or more times, and writes its answer from what came back. Because the tool description names the signals and their meaning, the model routes itself to the right ones.
market-pulse-bundle when you need several primitives at once. Watch the _apex_pricing block in each response to track spend.
Which signal for which decision
| The agent is deciding… | Reach for |
|---|---|
| Is the market trending, ranging, or in crisis? | regime-confluence, regime-micro |
| Is sentiment at an extreme? | fear-greed, fg-micro |
| Should I add to / re-enter a position? | dca-reentry-gate |
| Is this trade crowded / reversal-prone? | crowded-trade-detector |
| How strong is the conviction signal? | agent-conviction-score, apex-alpha-score |
| Where and when do I execute? | optimal-order-routing, slippage-forecast |
Try it without paying first
Point the tool at https://apexrunner.ai/signals/apex-trial while you wire up the loop — it's free and returns a real sample — then switch to the live signals once the plumbing works.