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 sentiment score you compute on your own server, a signal you've built over years, 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 feedsOn-demand tools
Fileendpoints.yamltools.yaml
Who callsEngine, automatically before every reviewThe agent, mid-decision, when it chooses to
Best forSignals the agent should always have in front of itLook-ups that only matter sometimes
ExampleA fear & greed score, a social-buzz indexA 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.

Say you track social-media buzz per coin on your own server, and you want the agent to treat a sudden buzz spike as a warning sign for chasing entries:

endpoints:
  - name: social_buzz
    url: https://alpha.yourserver.com/buzz
    identifiers: [buzz_score]
    per_market: true
    ttl_seconds: 60
    auth_header_env: MY_BUZZ_API_KEY

What each field does:

FieldWhat it does
nameA label for the feed. Shows up in health reporting.
urlYour HTTPS endpoint. Engine sends a small POST asking for values.
identifiersThe names of the numbers your feed returns (up to 4 per feed). These become part of the agent's vocabulary: write "skip entries when buzz_score is spiking" in your playbook and the agent knows exactly what you mean.
per_markettrue means one value per market in your universe; false means a single global value (like a macro flag).
ttl_secondsHow long a fetched value stays fresh before Engine asks again. From 1 second to 1 hour.
auth_header_envOptional. 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": "buzz_score", "markets": ["BTC-PERP", "DOGE-PERP"], "ts": "…" }

// Your server replies:
{ "values": { "BTC-PERP": 0.31, "DOGE-PERP": 0.92 } }

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.

Your endpoint has 8 seconds to reply. That's the default. If a tool legitimately needs longer (say it calls an LLM upstream), raise the limit per tool with timeout_ms, up to 30000:

tools:
  - name: second_opinion
    description: Runs an independent model review of a proposed trade.
    endpoint: https://yourserver.com/review
    timeout_ms: 20000

The setup health check waits the same window as a live call, so a green check means the tool fits in production too. (The check sends a fixed { "args": {}, "ping": true } payload; if your endpoint does real work on every request, add a fast branch for ping requests so the check reflects reachability, not your full compute time.) Use the smallest value that works: the agent's decision waits on your tool, so every extra second of budget is extra staleness on the market data it decides against.

If your signal takes longer than 30 seconds to compute, don't fight the timeout. A signal that takes minutes is a batch job: compute it on your own schedule, cache the result, and serve the latest value instantly. If it's a score the agent should always have in front of it, serve it as an endpoints.yaml feed with a suitable ttl_seconds. If it genuinely needs arguments at decision time, keep it a tool but return the most recent precomputed answer immediately, with a computed_at field in the response so the agent can judge freshness.

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:

  1. In endpoints.yaml or tools.yaml, reference a secret by an env-style name, like MY_ALPHA_TOKEN.
  2. After publishing, open Strategies, find your strategy card, and choose Manage secrets from its menu.
  3. 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

  1. On the Strategies page, choose Create your own strategy, then the Build locally tab.
  2. Download the starter template. It ships with STRATEGY.md, a commented tools.yaml and endpoints.yaml, and a references/ folder, so you're editing working examples rather than starting blank.
  3. Fill in your feeds or tools, then upload the folder.
  4. 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.
  5. Publish, then set any secret values in the Secrets panel.

Worked example: a custom data feed

A strategy anyone can read at a glance: buy BTC dips, but only when the crowd is fearful. It leans on one custom feed, a fear & greed score served from the author's own endpoint. The playbook treats fear as permission, not a trigger; the live market picture still has to show a dip worth buying, and the strategy says plainly what to do when the feed is down.

Fear & Greed Dip Buyer
STRATEGY.md
-----------
---
name: Fear & Greed Dip Buyer
description: Buy BTC pullbacks only when the crowd is fearful, using a custom fear & greed feed.
version: 1.0.0
tags: [btc, sentiment, custom-data]
---

# Fear & Greed Dip Buyer

Buy quality BTC pullbacks only when the crowd is fearful. The custom
`fear_greed` feed (0 = extreme fear, 100 = extreme greed) says when the
crowd is scared; the live market picture says whether the dip is worth
buying. Both have to agree.

## Mandate
Patient contrarian. Most days this strategy does nothing. It acts only
when fear is high and the market shows a clean pullback, never on fear
alone.

## Universe
BTC-PERP only.

## Entry Setups
- Long only when `fear_greed` is below 30 and BTC has pulled back to a
  level that held before, with selling pressure fading.
- Skip the entry if funding is heavily negative and getting worse, since
  that says the crowd is still capitulating.

## Sizing and Risk
About 4% of NAV at 2x leverage. One position at a time. Smaller size when
volatility is elevated.

## Position Management
Hold while the recovery makes progress. Take partial profit as
`fear_greed` climbs back above 50; the edge fades as fear does.

## Exit Doctrine
Exit if the pullback level breaks with conviction, or if `fear_greed`
rises above 70 while the position is on. Greed is the exit signal, not
the entry.

## Time Horizon
Swing: days to a couple of weeks, as long as the recovery holds.

## Abstain When
- `fear_greed` is between 30 and 70. No edge in the middle.
- The feed is unavailable.
- A major macro event lands within 24 hours.

endpoints.yaml
--------------
endpoints:
  - name: sentiment
    url: https://yourserver.example.com/fear-greed
    identifiers: [fear_greed]
    per_market: false
    ttl_seconds: 300

Worked example: an on-demand tool

The same idea with a tool instead of a feed: trade breakouts, but before entering, have the agent look up the news. The tool is declared once in tools.yaml; the playbook then simply says "check the news tool for the symbol" and the agent calls it at exactly that moment, not on every review.

News Sentiment Breakout
STRATEGY.md
-----------
---
name: News Sentiment Breakout
description: Trade breakouts only when price structure and fresh news/sentiment agree.
version: 1.0.0
tags: [news, breakout, sentiment, crypto]
---

# News Sentiment Breakout

Trade breakouts only when price structure and fresh news agree. The custom news
tool is the confirmation, not the trigger.

## Mandate
Event-confirmed breakouts only. A clean break with no supporting headline is a
pass; a headline with no price confirmation is a pass.

## Universe
BTC-PERP, ETH-PERP, and SOL-PERP.

## Entry Setups
**Long:** price breaks resistance with expanding volume and sentiment positive
and accelerating; check the news tool for the symbol and enter only if headlines
support the break.
**Short:** the mirror, on a breakdown with negative, accelerating sentiment.

## Sizing and Risk
About 5% of NAV at 2x leverage. Stop ~4%, target ~12%; daily loss budget ~3%.

## Position Management
Hold while the market keeps accepting the news; reduce if the catalyst impulse stalls.

## Exit Doctrine
Exit when the event is fully priced, price rejects the breakout, or follow-up
headlines contradict the thesis.

## Time Horizon
Short: hours to a couple of days, while the news is still being absorbed.

## Abstain When
- The news tool is unavailable.
- Headlines conflict with the price move.
- A high-volatility liquidation cascade is underway.

tools.yaml
----------
tools:
  - name: fetch_news
    description: Returns recent headlines and sentiment for a symbol.
    endpoint: https://api.example.com/news
    method: POST
    auth:
      type: bearer
      secret: NEWS_API_KEY
    input_schema:
      type: object
      properties:
        symbol: { type: string }
      required: [symbol]
    output_schema:
      type: object
      properties:
        headlines: { type: array }
        news_sentiment_score: { type: number }

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.