Custom tools and data
Plug your own data feeds and services into the agent: always-on custom feeds via endpoints.yaml, on-demand tools via tools.yaml, and reference files for depth.
The agent already reads a full market picture on every review: price, funding, open interest, volatility, order book, momentum, macro, news, and your account state. For most strategies that's plenty.
But some strategies have an edge that lives outside Engine: a regime model you run on your own server, a sentiment index you've built, a news service you pay for. This page covers the three ways to plug that in. None of them require changing how you write your playbook; they just extend what the agent can see and do.
Push or pull: which one do you need?
Both features connect the agent to an HTTPS endpoint you control. The difference is who initiates.
| Custom data feeds | On-demand tools | |
|---|---|---|
| File | endpoints.yaml | tools.yaml |
| Who calls | Engine, automatically before every review | The agent, mid-decision, when it chooses to |
| Best for | Signals the agent should always have in front of it | Look-ups that only matter sometimes |
| Example | A regime score, an on-chain flow metric | A news search, a deep liquidity report |
A good rule of thumb: if your playbook says "only trade when X agrees," X should be a data feed. If it says "before sizing up, check Y," Y should be a tool.
Custom data feeds
Declare a feed in endpoints.yaml and Engine fetches it automatically before every review, then merges the numbers into the market picture, right alongside price and funding. Your playbook can then reference those numbers by name in plain prose.
endpoints:
- name: regime
url: https://alpha.yourserver.com/eth/regime
identifiers: [regime_score]
per_market: true
ttl_seconds: 60
auth_header_env: MY_ALPHA_TOKEN
What each field does:
| Field | What it does |
|---|---|
name | A label for the feed. Shows up in health reporting. |
url | Your HTTPS endpoint. Engine sends a small POST asking for values. |
identifiers | The names of the numbers your feed returns (up to 4 per feed). These become part of the agent's vocabulary: write "when regime_score is above 0.7" in your playbook and the agent knows exactly what you mean. |
per_market | true means one value per market in your universe; false means a single global value (like a macro flag). |
ttl_seconds | How long a fetched value stays fresh before Engine asks again. From 1 second to 1 hour. |
auth_header_env | Optional. The name of a secret (set in the Secrets panel) that Engine sends as Authorization: Bearer …. |
Your server receives a JSON POST naming the identifier and the markets being asked about, and replies with the values:
// Engine sends:
{ "identifier": "regime_score", "markets": ["ETH-PERP"], "ts": "…" }
// Your server replies:
{ "values": { "ETH-PERP": 0.82 } }
For a global feed (per_market: false) the reply is just { "value": 0.4 }.
If your feed goes down, the agent knows. Requests time out after 2 seconds with one retry. On failure the value shows as unavailable rather than stale or zero, so a playbook line like "abstain when the feed is unavailable" works exactly as written.
Limits: up to 6 feeds per strategy, 4 identifiers each.
On-demand tools
Declare a tool in tools.yaml and the agent gets it alongside its built-in tools (order book, candles, news, memory). It calls yours by name whenever it decides the answer is worth the wait, and the result flows into that decision.
tools:
- name: fetch_news
description: Returns recent headlines and a sentiment score for a symbol.
endpoint: https://yourserver.com/news
method: POST
auth:
type: bearer
secret: NEWS_API_KEY
input_schema:
type: object
properties:
symbol: { type: string }
required: [symbol]
The description is the most important line: it's what the agent reads to decide when to call the tool. Write it the way you'd brief a colleague. "Returns recent headlines and a sentiment score for a symbol" tells the agent exactly when this is useful; a vague description means the tool sits unused, or gets called at the wrong times.
The input_schema describes what the agent should send (here: a symbol string), and an optional output_schema lets Engine sanity-check the response before the agent reads it. Tools can use GET, POST, PUT, PATCH, or DELETE, with optional bearer auth via a named secret.
If a tool call fails, the error goes back to the agent as information, not a crash: it can retry with different inputs, fall back to built-in data, or abstain, whatever your playbook implies.
Limits: up to 16 tools per strategy. A few names are reserved by the built-in toolkit (like get_orderbook and news_check); validation flags a collision immediately.
Reference files
Not everything belongs in the everyday playbook. Drop extra markdown files in a references/ folder and the agent loads them on its own when a setup calls for more depth: a regime-specific playbook, per-market tactics, a sizing matrix, past post-mortems.
The main playbook stays lean, and the depth is there when it matters. Up to 64 reference files, 64KB each.
Secrets
API keys never live in your bundle, and never appear in your published files. Instead:
- In
endpoints.yamlortools.yaml, reference a secret by an env-style name, likeMY_ALPHA_TOKEN. - After publishing, open Strategies, find your strategy card, and choose Manage secrets from its menu.
- Paste the actual value there. It's encrypted at rest, and Engine injects it only when calling your endpoint.
Anyone browsing your strategy in the marketplace sees the name, never the value.
Adding them to your strategy
- On the Strategies page, choose Create your own strategy, then the Build locally tab.
- Download the starter template. It ships with
STRATEGY.md, a commentedtools.yamlandendpoints.yaml, and areferences/folder, so you're editing working examples rather than starting blank. - Fill in your feeds or tools, then upload the folder.
- Hit Validate. Engine parses the bundle and live-probes every declared endpoint, so you find out your URL is unreachable before publishing, not on the first trade.
- Publish, then set any secret values in the Secrets panel.
A worked example
A minimal strategy that leans on one custom feed: the playbook treats the private score as a prior that must agree with live market context, and says plainly what to do when the feed is down.
STRATEGY.md
-----------
---
name: ETH Regime Filter
description: Trade ETH only when a private regime model agrees with live market context.
version: 1.0.0
tags: [eth, regime, custom-data]
---
# ETH Regime Filter
Trade ETH-PERP only when a private regime model agrees with the live market
setup. The custom feed is a prior, not a trigger.
## Mandate
Conservative and confirmation-driven. Trade rarely; the private score must agree
with market context, never override it.
## Universe
ETH-PERP only.
## Entry Setups
- A `regime_score` above 0.70 is supportive, not automatic.
- Volatility is normal and price structure agrees.
## Sizing and Risk
About 3% of NAV at 2x leverage; smaller when volatility is rising.
## Position Management
Hold while the regime score and the setup both hold; reduce as volatility expands.
## Exit Doctrine
Exit when the regime score decays or the original setup is invalidated.
## Time Horizon
Swing — hours to a few days, as long as the regime persists.
## Abstain When
- The private score conflicts with market context.
- The feed is unavailable.
endpoints.yaml
--------------
endpoints:
- name: regime
url: https://alpha.mycompany.com/eth/regime
identifiers: [regime_score]
per_market: true
ttl_seconds: 60
auth_header_env: MY_ALPHA_TOKEN
What's next
Supported markets covers where these strategies can trade, and Data your agent can see catalogs everything built in, so you only build feeds for what Engine doesn't already provide.