SERA-CryptoAgent is the open-source, standalone CLI distribution of SERA-Crypto — Sentient Foundation's SERA (Semantic Embedding & Reasoning Agent) architecture applied to crypto token research.
Conventional crypto agents route requests through long ReAct loops, where an LLM picks tools turn-by-turn. SERA instead precomputes embeddings of tool docstrings and category prompts, then matches the user's query against both — choosing the right API tools and the right response template in one shot, then executing tool calls in parallel. Per the SERA-Crypto announcement, this delivered state-of-the-art performance among open-source crypto agents (within 2% of GPT-5 Medium on the team's token-research benchmark), at average latency under 45 seconds, on a fully open-source model stack (MiniMax M2.5 + GPT-OSS).
Highlights:
- 44 crypto APIs across 7 providers — the public-only subset works with zero paid keys
- Embedding-based tool routing (top-k, threshold-gated) — no ReAct, parallel tool execution
- 11 category-specific prompt templates selected by embedding similarity
- Two-stage continuation flow with a sandboxed calculator phase
- Fully open-source default model stack: MiniMax M2.5 (tool calling) + GPT-OSS-120b (final synthesis & rephrase), swappable in
[sera/config.py](sera/config.py) - Langfuse tracing via OpenTelemetry (no-op until env keys are set)
Requires Python 3.12.x.
cd SERA-CryptoAgent
python3.12 -m venv .venv && source .venv/bin/activate
pip install -e .
cp .env.example .env # then fill LLM_API_KEY (EXA_API_KEY is recommended)
sera "What is the current price of Bitcoin?"Uses poetry.lock for reproducible installs:
cd SERA-CryptoAgent
poetry install
cp .env.example .env # then fill LLM_API_KEY (EXA_API_KEY is recommended)
poetry run sera "What is the current price of Bitcoin?"All keys live in .env. Non-secret tunables (models, base URLs, top-k) are in [sera/config.py](sera/config.py). Tools with missing keys are filtered out at startup — the LLM never sees them.
| Key | Status | Notes |
|---|---|---|
LLM_API_KEY |
required | Any OpenAI-compatible endpoint (Fireworks default; OpenAI, OpenRouter, etc. via [config.py](sera/config.py)) |
EMBEDDING_API_KEY |
optional | Embeddings for tool/category routing. Defaults to LLM_API_KEY if unset |
EXA_API_KEY |
recommended | Web search. Missing → [warn] at startup, agent falls back to APIs only |
COINGECKO_API_KEY |
optional | Leave empty for keyless public API; set for Demo or Pro key and higher on-chain limits |
COINGECKO_API_TIER |
optional | demo (default) | pro — must match your CoinGecko key type (only provider with a free/paid endpoint split) |
ARKHAM_API_KEY |
optional | Paid API only — wallet balances, transfers, holders. No free tier |
COINGLASS_API_KEY |
optional | Paid API only — OI, funding, liquidations, taker flow. No free tier |
CRYPTORANK_API_KEY |
optional | Paid API only (Sandbox or higher) — allocations, unlocks, funding, team, funds |
DATA_API_PROXY_URL |
optional | Route Arkham / Coinglass / CryptoRank through a Sentient data-API proxy instead of provider URLs directly |
LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_HOST |
optional | Langfuse tracing — no-op if keys are unset |
Providers needing no key: Binance global (api.binance.com), DefiLlama, CoinGecko free tier. These cover basic price / market / DeFi questions out-of-the-box.
See .env.example for a copy-paste template.
sera "What is the current price of Bitcoin?"The first line of output is prefixed with chat_id: — copy the ULID and use it for follow-ups:
chat_id: 01JBYR... # printed at the start of every run
sera --chat-id 01JBYR... "and what about ETH?"Sessions persist as JSON under .sera_sessions/.
If you installed with Poetry, prefix commands with poetry run:
poetry run sera "What is the current price of Bitcoin?"You can also run the entry point directly with python run.py "..." if you prefer not to install.
| Flag | Effect |
|---|---|
--chat-id <ulid> |
Resume an existing conversation (loads <ulid>.json from .sera_sessions/). Invalid IDs are rejected. |
--new-chat |
Force a fresh session even if --chat-id is also passed. |
-q, --quiet |
Silence diagnostic emissions ([plan], [step], [tool], …). The final response still streams. [error] messages still print regardless of this flag. |
User query
│
▼
[1] Follow-up rephrasing (CRYPTO_REPHRASER_PREFIX/SUFFIX + prior turns)
│
▼
[2] Coin resolution (forced LLM tool call → get_coin_info, strict=True)
│
▼
[3] Parallel:
├── EXA web search
└── Crypto data task (DATA FETCHER prompt + RAG-selected tools)
├── Round 1 LLM call (tools=auto, strict=True, retry up to 2x)
├── Flat asyncio.gather over all tool calls
└── Per-tool response filters + 100KB truncation fallback
│
▼
[4] Second-stage classifier (LLM tool call → classify_second_stage)
└── If enabled:
├── Phase 2A: extract coins from search → fetch their API data
└── Phase 2B: calculator phase (when needs_calculation=True)
│
▼
[5] Final response synthesis (streamed, tool_choice=none, max_tokens=16000,
UTC date/time + calculator-results section +
second_stage_context)
│
▼
[5b] Citation post-process (deterministic — strips or normalizes
<Citation /> tags per AGENT.enable_citations)
│
▼
[6] Format pass (second LLM call — spacing/LaTeX/table fixes)
│
▼
[7] Persist interaction to ChatSession
Key ideas:
- Embeddings replace the LLM router. Conventional crypto agents use long ReAct loops where an LLM picks tools turn-by-turn. SERA precomputes embeddings of tool docstrings and category prompts, then matches the rephrased query against both: tool embeddings select the top-k API tools (
_get_tools_using_rag), category embeddings select the final-response template (PromptsUtil). Selection is consistent per query category, tool calls run in parallel, and per the SERA-Crypto blog this brings average latency under 45 seconds. - Two-stage continuation. A classifier decides whether the answer needs follow-up tool calls (Phase 2A) or arithmetic (Phase 2B — calculator) before the final response is synthesized.
- Strict tool schemas. Every tool is introspected into an OpenAI strict-mode function schema, ensuring the LLM cannot hallucinate arguments.
- Compact tool payloads. Raw API JSON is trimmed in
[sera/tools/_filters.py](sera/tools/_filters.py)(field stripping, top-N lists, series downsampling).[sera/agent.py](sera/agent.py)applies a structure-aware 100KB fallback if a response is still oversized. - Two gated tools.
get_coin_info(coin-resolution phase) andcalculate_expression(calculator phase) are wired in but kept outside the main RAG pool so they cannot be invoked out of order.
Configuration toggles (sera/config.py)
Common flags you may want to flip:
| Flag | Default | Effect |
|---|---|---|
AGENT.enable_citations |
False |
When False, the response contains no <Citation /> / <CitationGroup /> markup; the LLM is also instructed to omit it. Flip to True to enable structured citations. |
AGENT.enable_citation_postprocessing |
True |
Normalizes [src_N] / (src_N) / <src_N> / bare src_N tokens to canonical <Citation id="src_N" />. Only effective when enable_citations=True. |
AGENT.enable_continuation_flow |
True |
Two-stage continuation (Phase 2A search-coin extraction + Phase 2B calculator). Disable for fewer LLM calls per query. |
AGENT.rag_top_k |
15 |
Number of tools selected per query by the embedding router. |
AGENT.rag_threshold |
0.3 |
Cosine-similarity floor for a tool to make the RAG selection. |
AGENT.crypto_task_retries |
2 |
Max retries on Round 1 tool-calling LLM failure. |
SERA-CryptoAgent/
├── run.py # CLI entry point — argparse, session bootstrap, streaming output
├── pyproject.toml # PEP 621 metadata + hatchling build + console script `sera`
├── poetry.lock # Pinned dependency graph (Python 3.12.x)
├── .env.example # Template for secrets — copy to .env and fill keys
├── LICENSE # Apache 2.0
├── README.md # This file
├── assets/ # Logos and images used in README
├── scripts/
│ └── demo_e2e.py # End-to-end smoke test running 5 demo queries
└── sera/
├── agent.py # SERAAgent — orchestrates the full pipeline (rephrase → tools → synthesis)
├── continuation.py # Two-stage continuation: phase 2A (follow-up tool calls) + 2B (calculator)
├── rephraser.py # Follow-up query rephraser (CRYPTO_REPHRASER_PREFIX + body + SUFFIX)
├── citation.py # Deterministic citation post-processors (normalize or strip <Citation /> tags)
├── session.py # ChatSession + JSON-backed SessionStore with ULID validation
├── history.py # Builds OpenAI-format chat history from prior interactions
├── schema.py # function_to_schema() — introspects Python tools → strict OpenAI schemas
├── llm.py # AsyncOpenAI client factory
├── embeddings.py # Embeddings client (Fireworks- / OpenAI-compatible)
├── api_providers.py # Provider attribution map for citing data sources in responses
├── emitter.py # ConsoleEmitter — streams [plan]/[step]/[tool] events to stdout
├── tracing.py # Langfuse via OpenTelemetry — opt-in via env keys
├── config.py # Single source of truth for all non-secret tunables
├── prompts/
│ ├── rephrase_prompts.py # CRYPTO_REPHRASER_PREFIX/SUFFIX + interaction body (used by rephraser.py)
│ ├── dynamic_prompts.py # BASE_PROMPT — analyst persona + formatting rules
│ ├── prompts_util.py # PromptsUtil — embedding-based final-response template selector
│ ├── prompt_descriptions.py # Category descriptions used by PromptsUtil
│ ├── prompts_map.py # Maps category name → template
│ ├── data_fetcher.py # DATA FETCHER + 2nd-stage tool-caller prefix + calculator-phase system prompt
│ ├── continuation_prompts.py # Classification + coin-extraction prompts (Phase 0 of continuation)
│ ├── coin_resolution.py # Forced-tool-call prompt for the coin resolution phase
│ ├── final_response.py # RESPONSE_CONSTRUCTION_GUIDELINES for final synthesis
│ └── tool_result_formatter.py # Formats raw tool JSON into concise context blocks
├── tools/ # 44 httpx-based API wrappers — auto-filtered if env key missing
│ ├── _common.py # @requires_env decorator + shared httpx client
│ ├── _filters.py # Response compaction — strip noise, top-N, downsample series
│ ├── coingecko.py # CoinGecko general (markets, gainers, global, contract, volatility)
│ ├── coingecko_onchain.py # CoinGecko on-chain (DEX pools, trending, holder distribution)
│ ├── binance.py # Binance global — book ticker, 24hr stats, order book, trades
│ ├── defillama.py # DefiLlama — chain TVL, protocol data, top pools, historical
│ ├── coinglass.py # Coinglass — OI, funding, liquidations, taker flow
│ ├── cryptorank.py # CryptoRank — allocations, unlocks, funding, team, drophunting
│ ├── arkham.py # Arkham — wallet balances, transfers, holders
│ └── calculator.py # Safe arithmetic — calculator phase only, not in RAG pool
└── search/
├── base.py # Search client abstract base
└── exa.py # EXA web search client
- Building an Open-Source Agent That Beats OpenAI, Gemini, and Perplexity — the SERA-Crypto announcement and architecture writeup.
Apache 2.0 — see LICENSE.
