Solana-native, real-time event subscription service for autonomous agents.
Eventmesh is the eyes and ears for on-chain agents. Describe what you want to react to in plain English — "any swap over 10k SOL on Orca SOL/USDC", "SOL price drops below 80 USDC on Raydium", "Jupiter TVL drops 5%", "any Polymarket Solana market crosses 60 cents" — and Eventmesh streams matching events straight into your agent over WebSocket, webhook, or stdin.
npx eventmeshcc subscribe "any trade over 10k SOL on SOL/USDC" --webhook https://agent.app/hookBuilt for the Solana agent stack: native DEX streaming via Helius, prediction-market signals, on-chain DeFi metrics, and a long tail of market data — all funnelled through one typed event bus your agent can subscribe to in a single line.
- Connectors stream from Solana's data plane and adjacent markets (Helius WebSocket for DEX trades, Polymarket / Kalshi for prediction markets, DefiLlama for protocol TVL, plus weather and sports). Every source is normalized into a single
CanonicalEventshape. - The compiler turns each agent's natural-language intent into a structured rule — a vector embedding plus optional MongoDB-style condition filters (
{ effectivePrice: { $lte: 80 } },{ baseAmount: { $gte: 10000 } }). - The matcher runs every incoming event against every active subscription, combining cosine similarity over embeddings with the structured filters — so an intent can be both semantic ("SOL price crash") and precise ("effectivePrice < 80 USDC").
- The delivery engine fans matches out to agents via WebSocket (live) or HTTP webhook (signed, retried, batched).
Everything is one Bun process plus Postgres and Redis. Self-host it next to your agent, run it locally, or point your agent at a shared instance.
- Sub-second on-chain visibility. The
sol-deficonnector subscribes to Helius's Enhanced WebSocket and parses Orca Whirlpool + Raydium (AMM v4 + CLMM) swaps, liquidity adds and removes in real time — token-pair-aware, automatically discovering pools. - Natural-language intents over structured data. Agents don't need to learn a DSL or babysit pollers. Say "big SOL/USDC sells" and the compiler emits a rule against
type,side,baseAmount,effectivePrice, etc. - One event bus, many sources. Subscribe to a Solana DEX swap, a Polymarket odds shift, and a DefiLlama TVL drawdown from the same agent loop with the same CLI.
- Local-first AI. Set
IS_LOCAL=trueand the intent compiler + embeddings run on-device via QVAC + llama.cpp — no external LLM calls, agent prompts stay on the host. - Built for autonomy. Webhook signing, retry, dedupe, and per-subscription delivery limits mean an agent can fire off thousands of subscriptions and trust the bus to behave.
- Solana trading and MEV agents reacting to swaps, liquidity events, and price thresholds on Orca / Raydium.
- Agents that combine on-chain signals with prediction-market or off-chain data (e.g., hedge a Polymarket position against a Solana DEX move).
- Notification and ops bots: TVL drawdowns on a tracked protocol, large-wallet activity, market resolution.
- A backend for any product that wants "tell me when X happens on Solana" semantics without writing per-source pollers.
┌──────────────────────────────────────────┐
external sources │ Eventmesh server │
────────────────── │ │
Helius Enhanced WS ──▶ │ Connectors ──▶ Event Queue (BullMQ) │
(Orca + Raydium) │ │ │ │
Polymarket WS ──▶ │ │ ▼ │ Solana agents
Kalshi REST ──▶ │ │ Processor │ ───▶ (WebSocket / CLI)
DefiLlama API ──▶ │ │ (matcher, │
ESPN scores ──▶ │ │ embeddings, │ Webhooks
Weather API ──▶ │ │ conditions) │ ───▶ (signed, retried,
│ │ │ │ batched)
│ └─▶ Postgres ◀─┤ │
│ (subs, ▼ │
│ events, Delivery Queue │
│ pgvector) + Batchers │
└──────────────────────────────────────────┘
│ │
▼ ▼
Postgres Redis
(pgvector) (BullMQ)
Key pieces (in server/src/):
| Path | Role |
|---|---|
connectors/ |
Pluggable source adapters — each exports a ConnectorDefinition (id, prompt, normalizer, validator, runner). |
domains/subscriptions/compiler.ts |
Compiles natural-language intent → embedding + condition rules (OpenRouter or on-device QVAC llama.cpp). |
engine/matcher.ts |
Evaluates an event against a subscription (cosine similarity + MongoDB-style operators with $or support). |
engine/processor.ts |
Per-event pipeline: matcher → delivery batcher. |
engine/delivery.ts |
Webhook signing, retry, dedupe; WebSocket fan-out. |
queue/ |
BullMQ event + delivery queues and workers. |
db/schema/ |
Drizzle tables: users, accounts, subscriptions, deliveries, connectors, webhook registrations. |
ws/ |
WebSocket upgrade handler and per-connection auth. |
domains/ |
Hono REST domains: auth, subscriptions, account, connectors. |
These ship registered out of the box and run with no per-connector keys:
defillama— Protocol TVL. Tracks TVL across DefiLlama-indexed protocols. Solana-native protocols (Jupiter, Marinade, Kamino, Jito, Orca, Raydium, Drift…) are first-class — point an agent at a protocol slug and react to TVL deltas, dominance shifts, or chain-level totals.polymarket— Polymarket prediction markets. Streams price/odds updates and resolutions over Polymarket's WebSocket. Useful for agents that hedge or arbitrage between on-chain positions and event-outcome markets.kalshi— Kalshi event contracts. Polled REST, normalized into the same canonical event shape so an agent can subscribe to crypto, macro, and sports contracts uniformly.- Sports — ESPN-backed connectors for
basketball,football(NFL),baseball,hockey,soccer,tennis. Score changes, status transitions, game-end. weather— current conditions via public weather APIs.
Reference connectors live under server/src/connectors/examples/. They aren't registered by default — copy the folder out (or add it to connectors/index.ts) and provide the listed env var:
| Connector | Env var | What it does |
|---|---|---|
sol-defi |
HELIUS_API_KEY |
Solana DEX streaming via Helius — live swaps, liquidity adds/removes on Orca Whirlpool and Raydium (AMM v4 + CLMM), token-pair-aware with automatic pool discovery. |
alchemy |
ALCHEMY_AUTH_TOKEN |
EVM + Solana on-chain webhooks via Alchemy (address activity, NFT activity). |
coindesk |
CRYPTOCOMPARE_API_KEY |
Crypto price polling via CryptoCompare. |
news |
NEWSAPI_API_KEY |
Top headlines via thenewsapi.com (polled every 5 min). |
cryptoprices |
— | Public crypto price polling (no key). |
Drop a folder under server/src/connectors/<name>/ with connector.ts, prompt.ts, normalizer.ts, validator.ts, then register it in connectors/index.ts. The sol-defi example under connectors/examples/sol-defi/ is a good reference for streaming connectors with structured filters; server/AGENTS.md has the full contract.
- Runtime: Bun
- API: Hono (REST + WebSocket, OpenAPI/Swagger at
/docs) - DB: PostgreSQL with pgvector, via Drizzle ORM
- Queues: Redis + BullMQ
- AI: OpenRouter for embeddings + intent compilation, or fully local via QVAC (llama.cpp) when
IS_LOCAL=true - Monorepo: Turbo, three workspaces —
server/,shared/(DTOs),cli/(eventmeshcc) - Lint/format: Biome (tabs, double quotes)
git clone https://github.com/shipmesh/eventmesh-engine.git
cd eventmesh
cp .env.example .env
# Edit .env: at minimum set POSTGRES_PASSWORD, OPENROUTER_API_KEY (or IS_LOCAL=true)
docker compose up --buildThis brings up Postgres (with pgvector), Redis, and the API on http://localhost:3000. Open http://localhost:3000/docs for the OpenAPI explorer and http://localhost:3000/health for a liveness check.
bun install # installs + builds shared/server via postinstall
docker compose up db redis -d # just the infra
cp .env.example .env # set DATABASE_URL, REDIS_URL, OPENROUTER_API_KEY
bun run dev # runs server (and any active workspaces)bun run test:docker # spins up an ephemeral Postgres on :5433 (tmpfs), runs all tests, tears downTests are integration tests — they hit real routes via app.request() against a real DB and (where applicable) real third-party APIs. Pass API keys through env vars; mocks are a last resort.
| Var | Purpose |
|---|---|
DATABASE_URL |
Postgres connection string (must have the pgvector extension available). |
REDIS_URL |
Redis for BullMQ event + delivery queues. |
OPENROUTER_API_KEY |
Intent compilation + embeddings — unless IS_LOCAL=true. |
Both DATABASE_URL and REDIS_URL have sensible localhost defaults, so a docker compose up flow only needs OPENROUTER_API_KEY (or IS_LOCAL=true) and POSTGRES_PASSWORD.
| Var | Default | Purpose |
|---|---|---|
IS_LOCAL |
false |
Run completions + embeddings on-device via QVAC + llama.cpp. No OpenRouter calls, no data leaves the host. |
NODE_ENV |
development |
— |
PORT |
3000 |
— |
LOG_LEVEL |
info |
fatal / error / warn / info / debug / trace |
PUBLIC_URL |
— | Public base URL (used for outbound webhook signing). |
COMPILER_ROUTER_MODEL |
openai/gpt-oss-20b |
Compiler router model (OpenRouter slug). |
COMPILER_SPECIALIST_MODEL |
openai/gpt-oss-20b |
Compiler specialist model (OpenRouter slug). |
FUZZY_MATCH_MIN_SCORE |
0.4 |
Minimum fuzzy match score (0..1) for entity resolution. |
Only set these if you enable the matching connector (see Connectors):
| Var | Connector |
|---|---|
HELIUS_API_KEY |
sol-defi (example) |
ALCHEMY_AUTH_TOKEN |
alchemy (example) |
CRYPTOCOMPARE_API_KEY |
coindesk (example) |
NEWSAPI_API_KEY |
news (example) |
See .env.example for the full list with defaults.
npx eventmeshcc login # auth via the running server
npx eventmeshcc connectors # list available sources
npx eventmeshcc subscribe "any swap over 10k SOL on SOL/USDC" --active # Solana DEX
npx eventmeshcc subscribe "Jupiter TVL drops more than 5% in an hour" --active # DefiLlama
npx eventmeshcc list # your subscriptions
npx eventmeshcc listen <id> # tail matches over WebSocket
npx eventmeshcc subscribe "SOL drops below 80 USDC" --webhook https://... # webhook deliveryBy default the CLI talks to http://localhost:3000; override with --server or EVENTMESH_SERVER_URL.
curl -X POST http://localhost:3000/api/subscriptions \
-H "Authorization: Bearer $EVENTMESH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"intent":"any trade over 10k SOL on SOL/USDC","sensitivity":"balanced","isActive":true}'Full schema at http://localhost:3000/docs.
Webhook deliveries are batched, retried with backoff, and signed. Register a webhook URL on a subscription (or per-account in domains/webhooks/) and verify the signature on your side. URLs are validated against loopback / private / metadata addresses before being accepted.
.
├── server/ # Hono backend — connectors, engine, queues, REST + WS
├── shared/ # DTOs and types shared across workspaces
├── cli/ # eventmeshcc — npm CLI + thin WebSocket layer
├── scripts/ # test runner (Dockerized Postgres)
├── docker-compose.yml # local stack
├── docker-compose.test.yml # ephemeral test DB
├── Dockerfile
├── turbo.json
├── biome.json
└── .env.example
Workspace dependency order is shared ← server ← cli. Turbo handles build ordering; the postinstall hook prebuilds shared and server so types are available immediately after bun install.
Issues and PRs are welcome. Before submitting:
bun run format # Biome
bun run type-check
bun run test:dockerIf you're adding a connector, follow the checklist in server/AGENTS.md and include tests that exercise the real upstream API.
Elastic License 2.0 — source-available.
You can:
- Run Eventmesh in production, including for commercial purposes.
- Modify it, embed it inside your own product, and redistribute the source.
- Self-host it for your team, your customers, or your agents.
You cannot:
- Offer Eventmesh to third parties as a hosted or managed service that exposes a substantial set of its features (i.e. no reselling Eventmesh-as-a-service).
- Remove or obscure the licensor's notices.
If you want to host Eventmesh as a paid service for others, reach out for a commercial license.