Construire une pile de deux agents: agent de recherche + gardien d'exécution
Auteur: Équipe FXMacroData
Publié: 21 mai 2026
Les robots FX à un seul agent échouent pour une raison simple: le même modèle qui génère des idées est également autorisé à les approuver. Les effectifs non agricoles des États-Unis, une erreur de raisonnement peut se transformer en risque de position.
Ce guide montre une architecture plus sûre: responsabilités divisées entre deux agents. Le premier agent effectue des études de marché et propose des configurations. Le deuxième agent est un gardien de porte strict qui ne peut approuver, redimensionner ou rejeter des propositions basées sur des règles de risque dur.
À la fin, vous aurez un flux de travail pratique pour deux agents. Le taux de change Je suis désolé . Le taux de change qui prend en charge à la fois l'intégration directe des API REST et l'integration des outils basés sur MCP.
Pré-requis
- Python 3.10 ou plus.
- Une clé d'API FXMacroData de Gestion des APIJe suis désolé .
- Un point final de LLM pour les agents de recherche et de garde-porte.
- Familiarité de base avec les API JSON et HTTP.
Installer des dépendances:
pip install requests python-dotenv pydantic
Créez un .env fichier:
FXMD_API_KEY=your_fxmacrodata_key
RESEARCH_MODEL=claude-or-hermes
GATEKEEPER_MODEL=claude-or-hermes
MAX_RISK_PCT=0.50
Étape 1: définir des rôles stricts pour les deux agents
Ce qu' il faut faire: Fermez les responsabilités avant d'écrire du code.
- Agent de recherche: lit le contexte macro + marché et propose des candidatures.
- L'agent gardien de porte: valide uniquement les contraintes. Il ne peut pas inventer de nouveaux métiers, seulement approuver/rejeter/réduire la taille.
Pourquoi cela compte: Cette séparation empêche un modèle unique de contourner les contrôles des risques lorsque la confiance est élevée mais que les preuves sont faibles.
Étape 2: extraire le contexte structuré avec des appels REST directs
Ce qu' il faut faire: Les données de recherche sont fournies par FXMacroData afin que l'agent de recherche obtienne des données propres au lieu de titres non structurés.
curl "https://fxmacrodata.com/api/v1/calendar/usd?api_key=YOUR_API_KEY"
curl "https://fxmacrodata.com/api/v1/announcements/eur/inflation?api_key=YOUR_API_KEY"
curl "https://fxmacrodata.com/api/v1/announcements/gbp/unemployment?api_key=YOUR_API_KEY"
curl "https://fxmacrodata.com/api/v1/forex?base=EUR"e=USD&api_key=YOUR_API_KEY"
Pourquoi cela compte: Les champs structurés et cohérents donnent aux deux agents la même source de vérité et rendent la validation déterministe.
Le collecteur Python minimum:
import os
import requests
from datetime import datetime, timezone
API = "https://fxmacrodata.com/api/v1"
KEY = os.environ["FXMD_API_KEY"]
def fxmd_get(path, **params):
r = requests.get(
f"{API}{path}",
params={"api_key": KEY, **params},
timeout=25,
)
r.raise_for_status()
return r.json()
def build_market_context():
return {
"asof_utc": datetime.now(timezone.utc).isoformat(),
"calendar_usd": fxmd_get("/calendar/usd").get("data", [])[:8],
"calendar_eur": fxmd_get("/calendar/eur").get("data", [])[:8],
"eur_inflation": fxmd_get("/announcements/eur/inflation").get("data", [])[-1:],
"gbp_unemployment": fxmd_get("/announcements/gbp/unemployment").get("data", [])[-1:],
"eurusd": fxmd_get("/forex", base="EUR", quote="USD").get("data", [])[-48:],
"gbpusd": fxmd_get("/forex", base="GBP", quote="USD").get("data", [])[-48:],
}
Étape 3: Générer des candidats au métier avec l'agent de recherche
Ce qu' il faut faire: Demandez à l'agent de recherche uniquement pour les candidats de métiers structurés.
{
"pair": "EUR/USD",
"bias": "long|short|flat",
"thesis": "string",
"confidence": 0.0,
"entry_zone": "string",
"invalidation": "string",
"event_risks": ["string"]
}
Pourquoi cela compte: Un schéma fixe permet au gardien de passerelle d'appliquer des règles sur des champs prévisibles au lieu d'essayer d'analyser du texte libre.
Étape 4: appliquer les règles de risque dur dans l'agent gardien
Ce qu' il faut faire: faire passer chaque candidat à travers un deuxième modèle ou un validateur de règles avec des limites strictes.
Exemple de politique:
- Le risque maximal par transaction est de 0,50% du capital.
- Aucune nouvelle transaction dans les 15 minutes suivant la sortie de la calendrier de sortieJe suis désolé .
- Niveau d'invalidation obligatoire
- Rejeter si la confiance est inférieure à 0,60.
Porte pydactique et sortie de décision:
from pydantic import BaseModel, Field
class Candidate(BaseModel):
pair: str
bias: str
thesis: str
confidence: float = Field(ge=0.0, le=1.0)
entry_zone: str
invalidation: str
event_risks: list[str]
class GateDecision(BaseModel):
status: str # approve, resize, reject
approved_size_pct: float
reason: str
def gate(candidate: Candidate, max_risk_pct: float = 0.50) -> GateDecision:
if candidate.confidence < 0.60:
return GateDecision(status="reject", approved_size_pct=0.0, reason="Low confidence")
if not candidate.invalidation.strip():
return GateDecision(status="reject", approved_size_pct=0.0, reason="Missing invalidation")
proposed = 0.50 if candidate.confidence >= 0.75 else 0.30
size = min(proposed, max_risk_pct)
return GateDecision(status="approve", approved_size_pct=size, reason="Within policy")
Pourquoi cela compte: Même si l'agent de recherche a une mauvaise lecture, le gardien peut toujours bloquer les configurations trop grandes ou faibles.
Étape 5: Ajouter le chemin d'intégration MCP (flux de travail des agents natifs de l'outil)
Ce qu' il faut faire: exposer FXMacroData via MCP afin que les frameworks d'agents puissent appeler des outils nativement au lieu de créer une colle REST personnalisée pour chaque bot.
Démarrez un serveur MCP basé sur Python via uvxLe texte est le suivant:
uvx fxmacrodata-mcp --transport http --server-url https://fxmacrodata.com/mcp
Exemple de configuration du client:
{
"mcpServers": {
"fxmacrodata": {
"command": "uvx",
"args": [
"fxmacrodata-mcp",
"--transport",
"http",
"--server-url",
"https://fxmacrodata.com/mcp"
]
}
}
}
Exemple de schéma d'appel d'outils MCP pour votre agent de recherche:
{
"name": "get_fx_calendar_and_spot",
"description": "Get upcoming macro events and current spot context for selected pairs",
"input_schema": {
"type": "object",
"properties": {
"currencies": {
"type": "array",
"items": { "type": "string" }
},
"pairs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"base": { "type": "string" },
"quote": { "type": "string" }
},
"required": ["base", "quote"]
}
}
},
"required": ["currencies", "pairs"]
}
}
Exemple d'invocation d'agent (chemin MCP):
Research Agent:
"Using the fxmacrodata MCP tools, pull today's USD/EUR/GBP calendar and spot for EUR/USD and GBP/USD.
Return up to 3 candidate setups in strict JSON schema."
Gatekeeper Agent:
"Validate each candidate against risk policy v1. Reject anything violating confidence,
size, invalidation, or event-window constraints. Return approve/resize/reject with reason."
Pourquoi cela compte: MCP réduit la dérive d'intégration à mesure que votre pile grandit, en particulier lorsque vous exécutez plusieurs agents ou fournisseurs de modèles d'échange.
Étape 6: Envoyer les sorties à l'examen humain, puis à l"API du courtier
Ce qu' il faut faire: Envoyez les transactions approuvées aux systèmes d'exécution après confirmation humaine dans les premières versions.
Pourquoi cela compte: Cela crée une boucle auditable et vous protège lors de changements de mode ou de modèle.
[FX Two-Agent Candidate]
Pair: EUR/USD
Research Bias: Long
Gatekeeper: Approve
Approved Size: 0.30%
Reason: Confidence 0.71, invalidation present, no high-impact event in 15m window.
Ce que vous avez construit
Vous avez maintenant une architecture FX à deux agents qui sépare la génération d'idées de l'approbation des risques, prend en charge l'intégration directe REST et prend également en charge la mise en œuvre d'outils basés sur MCP via uvxIl s'agit d'une base plus solide que les robots à agent unique, car les candidats au commerce doivent survivre à une porte de politique indépendante avant l'exécution.
Suivant: ajouter une couche de commutateur qui force automatiquement . reject Vous pouvez également ajouter des contraintes de session à partir de Sessions de change et le contexte de positionnement de Le COTJe suis désolé .