This document defines the narrow write contract from hermes-mcp to trader-mcp.
Keep Hermes in charge of decisions and keep Trader in charge of safe application.
Hermes should send one explicit control decision. Trader should validate it, apply it if safe, and return a structured result.
keep is not a Trader write action. Hermes may record keep on its own side.Trader exposes one canonical Hermes write tool:
apply_control_decision(payload)Hermes should not need to combine multiple Trader tools to express one decision.
These may still exist internally or for operator use, but they are not the Hermes contract:
control_strategy(...)set_strategy_policy(...)switch_strategy(...)pause_strategy(...)resume_strategy(...)reconcile_instance(...)They are runtime helpers, not the cross-system write boundary.
The Hermes write contract supports only these actions:
switchpauseresumeset_risk_modeNot supported here:
keep{
"decision_id": "dec_2026_04_16_001",
"concern_id": "qndd8o9ppop6:xrpusd",
"account_id": "qndd8o9ppop6",
"market_symbol": "xrpusd",
"action": "switch",
"target_strategy_id": "0c555fee-e4c8-4543-ae70-c132517017e1",
"expected_active_strategy_id": "9cf29124-65a7-4950-ac18-65f938e0239b",
"risk_mode": "normal",
"reason": "trend strategy still fits the directional narrative",
"confidence": 0.83,
"dry_run": false,
"override": false,
"requested_at": "2026-04-16T20:15:00Z"
}
decision_idconcern_idaccount_idmarket_symbolactionreasonconfidenceswitchtarget_strategy_idset_risk_moderisk_modeexpected_active_strategy_id is strongly recommendeddecision_idStable id from Hermes. Trader stores it and uses it for audit linkage and idempotency checks.
concern_idThe account-market concern Hermes is acting on.
expected_active_strategy_idWhat Hermes believes is active right now.
If provided and Trader sees something else, Trader should reject unless override=true.
reasonHuman-readable explanation. Short, concrete, stable enough for audit logs.
confidenceNormalized float in [0, 1].
Trader does not have to trust it blindly, but may use it in guardrails.
dry_runValidate and simulate only. No state-changing action should occur.
overrideExplicit emergency bypass for guarded rejection paths. Use sparingly and always record it.
{
"ok": true,
"status": "applied",
"decision_id": "dec_2026_04_16_001",
"concern_id": "qndd8o9ppop6:xrpusd",
"action": "switch",
"from_strategy_id": "9cf29124-65a7-4950-ac18-65f938e0239b",
"to_strategy_id": "0c555fee-e4c8-4543-ae70-c132517017e1",
"risk_mode": "normal",
"dry_run": false,
"validation": {
"concern_match": true,
"account_match": true,
"market_match": true,
"expected_active_match": true,
"target_exists": true,
"target_runnable": true
},
"warnings": [],
"errors": [],
"result": {
"mode_change": "applied",
"reconciled": true
},
"applied_at": "2026-04-16T20:15:01Z"
}
appliedrejectednoopfailedappliedValidation passed and Trader changed state.
rejectedTrader refused the request due to validation or safety rules. This is a valid control outcome.
noopThe requested state already exists. Example: Hermes asks to resume a strategy that is already active.
failedTrader attempted the action but could not complete it due to runtime or persistence failure.
Trader should validate at least the following:
account_id matches the target strategy or concern.market_symbol matches the target strategy or concern.target_strategy_id exists for switch.expected_active_strategy_id is provided, it matches reality unless override=true.confidence is a valid numeric value in range.Version 0.1 implements a small set of safety gates:
override=trueCurrent implementation also records each attempt in Trader audit storage and reconciles the affected strategy runtime after an applied state change.
Trader should treat decision_id as an idempotency key.
Repeated submissions of the same already-applied decision should not reapply the state transition.
Trader should persist every Hermes action attempt, including:
A rejected action is still important and should be stored.
Hermes read path should stay separate from Hermes write path.
list_strategies()get_strategy()apply_control_decision(payload)Avoid proliferating extra Hermes-facing tools unless a real gap appears.
apply_control_decision(payload) may internally call existing runtime helpers:
control_strategy(...)set_strategy_policy(...)reconcile_instance(...)switch_strategy(...)But Hermes should only see one write entry point.
Keep this contract small. Future versions should extend it only when a real decision or execution need appears. If a new field does not improve safety, auditability, or decision fidelity, it probably does not belong here.