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 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 regime score, an on-chain flow metricA 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:

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 "when regime_score is above 0.7" 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": "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:

  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.

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.

ETH Regime Filter
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.