Productivity

alva

alva-ai/skills · updated Apr 8, 2026

$npx skills add https://github.com/alva-ai/skills --skill alva
summary

Alva is an agentic finance platform. It provides unified access to 250+

  • financial data sources spanning crypto, equities, ETFs, macroeconomic
  • indicators, on-chain analytics, and social sentiment -- including spot and
  • futures OHLCV, funding rates, company fundamentals, price targets, insider and
  • senator trades, earnings estimates, CPI, GDP, Treasury rates, exchange flows,
  • DeFi metrics, news feeds, social media and more!
skill.md

Alva

What is Alva

Alva is an agentic finance platform. It provides unified access to 250+ financial data sources spanning crypto, equities, ETFs, macroeconomic indicators, on-chain analytics, and social sentiment -- including spot and futures OHLCV, funding rates, company fundamentals, price targets, insider and senator trades, earnings estimates, CPI, GDP, Treasury rates, exchange flows, DeFi metrics, news feeds, social media and more!

What Alva Skills Enables

The Alva skill connects any AI agent or IDE to the full Alva platform. With it you can:

  • Access financial data -- query any of Alva's 250+ data SDKs programmatically, or bring your own data via HTTP API or direct upload.
  • Run cloud-side analytics -- write JavaScript that executes on Alva Cloud in a secure runtime. No local compute, no dependencies, no infrastructure to manage.
  • Build agentic playbooks -- create data pipelines, trading strategies, and scheduled automations that run continuously on Alva Cloud.
  • Deploy trading strategies -- backtest with the Altra trading engine and run continuous live paper trading.
  • Release and share -- turn your work into a hosted playbook web app at https://alva.ai/u/<username>/playbooks/<playbook_name>, and share it with the world.
  • Remix existing playbooks -- take any published playbook as a template, read its feed scripts and HTML source, customize parameters/logic/UI, and deploy as your own new playbook.

In short: turn your ideas into a forever-running finance agent that gets things done for you.

Pre-flight

Run these checks on first use each session before doing anything else.

1. Version Check

bash "<this skill's directory>/scripts/version_check.sh"
  • No output → up to date, proceed.
  • Output present → display to user, apply the update, then proceed.

2. API Key

Variable Required Description
ALVA_API_KEY yes Your API key (alva.ai)
ALVA_ENDPOINT no API base URL. Defaults to https://api-llm.prd.alva.ai

The version check (Step 1) creates a symlink ~/.alva.env → this skill's .env. Each Bash tool call is an isolated shell, so every command that needs Alva variables must source first:

source ~/.alva.env && curl -s -H "X-Alva-Api-Key: $ALVA_API_KEY" "$ALVA_ENDPOINT/api/v1/me"

If ALVA_API_KEY is missing or empty after sourcing, ask the user whether they already have a key:

  • Has a key — ask them to paste it, write it to .env, and verify with the command above.

    On success, suggest persisting in their shell profile. Then offer starting points:

    • "Ask me something like 'Who's been buying NVDA insider shares this month?'"
    • "Or build a live dashboard, backtest a strategy, or set up a data pipeline."
  • No key — sign up at alva.ai, create a key under Settings → API Keys, paste it back, then verify as above.

.env format:

ALVA_API_KEY=alva_...
ALVA_ENDPOINT=https://api-llm.prd.alva.ai
last_check=...
ENV=local

ALVA_API_KEY authenticates to Alva itself. Third-party vendor secrets belong in Alva Secret Manager (require("secret-manager")).

3. User Profile

source ~/.alva.env && curl -s -H "X-Alva-Api-Key: $ALVA_API_KEY" "$ALVA_ENDPOINT/api/v1/me"
{"id":1, "subscription_tier":"free", "telegram_username":"alice_tg", "username":"alice"}

Session variables:

  • username — for public URLs and ALFS paths.
  • subscription_tier"pro" or "free" (default). Determines release flow (Step 7): pro can keep playbooks private.
  • telegram_username — if set, recommend push-enabled feeds; if null, guide user to connect Telegram first.

Making API Requests

All API examples use HTTP notation (METHOD /path). Every request requires X-Alva-Api-Key unless marked (public, no auth).

Every bash call must source ~/.alva.env first since each shell is isolated.

# Authenticated
source ~/.alva.env && curl -s -H "X-Alva-Api-Key: $ALVA_API_KEY" "$ALVA_ENDPOINT{path}"

# Authenticated + JSON body
source ~/.alva.env && curl -s -H "X-Alva-Api-Key: $ALVA_API_KEY" -H "Content-Type: application/json" \
  "$ALVA_ENDPOINT{path}" -d '{body}'

# Public read (no API key)
curl -s "${ALVA_ENDPOINT:-https://api-llm.prd.alva.ai}{path}"

Communication

No ALFS paths, API payloads, cronjob IDs, raw function names, internal jargon, or implementation details in user-facing responses. Say what it DOES, not how it works. These details are operating instructions for you, not content for the user.

Lead with the result, not the process. The first thing the user reads should be what they got ("Your dashboard is live at …"), not what you did ("I deployed 3 feeds and wrote the HTML"). During multi-step builds, give a short status update at each milestone so the user knows work is progressing.

Request Routing

Request Type Core Objectives
Dashboard / Playbook Identify the needed data sources, validate the data flow, and produce a usable dashboard or playbook when the user wants a shareable artifact
Backtest / Strategy Use Altra, run the backtest correctly, and always produce a visual playbook (equity curve, trade log, metrics) alongside the text summary. Optionally deploy as live paper trading.
Data Query Fetch the requested data accurately and return it directly unless the user asks for a richer artifact
Remix Reuse the source artifact, apply the requested changes, and return an updated result that matches the requested customization

Guided Planning

For all routes except Data Query, present a plan and get user approval before building. Even seemingly clear requests ("build a BTC dashboard") have real choices — which data, timeframe, widgets — that are cheaper to resolve upfront than to rebuild.

  1. Understand intent — Ask clarifying questions one at a time, prefer multiple-choice. Focus on what's missing: asset, scope, output type, or purpose. Skip this step if the request already specifies all of these.
  2. Propose approaches — Offer 2-3 concrete options with trade-offs. Lead with your recommendation.
  3. Confirm the plan — List the specific feeds and widgets (5-8 lines, no implementation details). Build only after approval.

If the user says "just do it" at any point, skip planning for the rest of the session.

Completion Gate

For Dashboard/Playbook and Backtest/Strategy requests, the default goal is to leave the user with a result they can actually use. In many cases that means a released playbook and a published_url, but do not force that path if the user only asked for code, analysis, debugging help, or an intermediate artifact.

Before finishing, verify that the delivered result matches the user's actual goal. When a shareable playbook was part of the task, verify:

  • A playbook was released and a published_url was returned

Content Legitimacy Rules

These rules are non-negotiable. Violations produce misleading playbooks that display fabricated data as if it were real. Every rule below applies to all playbook builds.

Data Sourcing

  1. All quantitative data displayed in charts, tables, or KPI cards MUST originate from Alva feeds (SDK modules or BYOD via require("net/http")). Never hardcode data as inline JavaScript literals in playbook HTML.

  2. Playbook HTML MUST fetch data at runtime from feed output paths:

    const resp = await fetch(
      "$ALVA_ENDPOINT/api/v1/fs/read?path=/alva/home/<user>/feeds/<name>/v1/data/<group>/<output>/@last/<n>",
    );
    const data = await resp.json();
    renderChart(data);
    

    Static content (labels, colors, layout config) is fine. Quantitative data is not — it must flow through the feed pipeline.

Prohibited Data Sources for Charts and Tables

  1. WebSearch / WebFetch results must NOT be embedded as data. Web search is only legitimate for: reading documentation, finding API endpoints for BYOD, understanding user requirements. Never inject web search results as static data literals in feed scripts or playbook HTML.

  2. LLM / ADK output must NOT be presented as factual sourced data. ADK is for reasoning, classification, summarization, and synthesis of real data — not for generating numbers, statistics, events, or reports that claim to be from real sources. If ADK produces quantitative output, it must be clearly labeled as "AI-generated analysis".

  3. Agent training knowledge must NOT fill data gaps. If an SDK does not have the requested data type, report the gap as a blocker. Do not invent data from your own knowledge to fill the hole.

SDK Coverage Gaps

  1. When an SDK partition lacks the requested data type, report it as a blocker. For example, if equity_events_calendar only has dividends/splits but the user wants FDA events, report this gap. Suggest BYOD alternatives (require("net/http") to a live API) if one exists. Do NOT fabricate events.

  2. When >20% of requested symbols fail SDK lookup, report a data-quality blocker. Do not silently substitute with estimated or fabricated values marked live: false.

Description and Provenance Accuracy

  1. Playbook descriptions and methodology sections must only list data sources that were actually called successfully. Do not claim "Brave Search", "ClinicalTrials.gov", or any other source unless the feed script actually fetches from it at runtime.

  2. Update frequency claims must match actual deployment. If cronjob deployment failed, do not claim "updated every N hours" in the playbook description. Either fix the cronjob or remove the claim.


Capabilities & Common Workflows

1. ALFS (Alva FileSystem)

The foundation of the platform. ALFS is a cloud filesystem with per-user isolation. Every user has a private home directory; all paths are private by default and only accessible by the owning user. Public read access can be explicitly granted on specific paths via grant. Scripts, data feeds, playbook assets, and shared libraries all live on ALFS.

Key operations: read, write, mkdir, stat, readdir, remove, rename, copy, symlink, chmod, grant, revoke.

2. JS Runtime

Run JavaScript on Alva Cloud in a sandboxed V8 isolate. Code executed inside Alva's /api/v1/run runtime runs entirely on Alva's servers -- it cannot access the host machine's filesystem, environment variables, or processes. The runtime has access to ALFS, all 250+ SDKs, HTTP networking, LLM access, and the Feed SDK.

3. SDKHub

250+ built-in financial data SDKs. To find the right SDK for a task, use the two-step retrieval flow:

  1. Pick a partition from the index below.
  2. Call GET /api/v1/sdk/partitions/:partition/summary to see module summaries, then load the full doc for the chosen module.

SDK doc lookup is mandatory. Always look up SDK documentation before writing any feed script. Do not guess function signatures, parameter names, or response shapes from memory. The doc lookup ensures you use the correct module, call the right function, and handle the actual response format.

SDK Partition Index

Partition Description
spot_market_price_and_volume Spot OHLCV for crypto and equities. Price bars, volume, historical candles.
crypto_futures_data Perpetual futures: OHLCV, funding rates, open interest, long/short ratio.
crypto_technical_metrics Crypto technical & on-chain indicators: MA, EMA, RSI, MACD, Bollinger, MVRV, SOPR, NUPL, whale ratio, market cap, FDV, etc. (20 modules)
crypto_exchange_flow Exchange inflow/outflow data for crypto assets.
crypto_fundamentals Crypto market fundamentals: circulating supply, max supply, market dominance.
crypto_screener Screen crypto assets by technical metrics over custom time ranges.
company_crypto_holdings Public companies' crypto token holdings (e.g. MicroStrategy BTC).
equity_fundamentals Stock fundamentals: income statements, balance sheets, cash flow, margins, PE, PB, ROE, ROA, EPS, market cap, dividend yield, enterprise value, etc. (31 modules)
equity_estimates_and_targets Analyst price targets, consensus estimates, earnings guidance.
equity_events_calendar Dividend calendar, stock split calendar.
equity_ownership_and_flow Institutional holdings, insider trades, senator trading activity.
stock_screener Screen stocks by sector, industry, country, exchange, IPO date, earnings date, financial & technical metrics. (9 modules)
stock_technical_metrics Stock technical indicators: beta, volatility, Bollinger, EMA, MA, MACD, RSI-14, VWAP, avg daily dollar volume.
etf_fundamentals ETF holdings breakdown.
macro_and_economics_data CPI, GDP, unemployment, federal funds rate, Treasury rates, PPI, consumer sentiment, VIX, TIPS, nonfarm payroll, retail sales, recession probability, etc. (20 modules)
technical_indicator_calculation_helpers 50+ pure calculation helpers: RSI, MACD, Bollinger Bands, ATR, VWAP, Ichimoku, Parabolic SAR, KDJ, OBV, etc. Input your own price arrays.
feed_widgets Social & news subscription feeds: news, Twitter/X, YouTube, Reddit, podcasts. For subscribing to specific accounts/channels.

For unstructured content — news articles, social discussions, videos, podcasts — see Content Search below.

You can also bring your own data by uploading files to ALFS or fetching from external HTTP APIs within the runtime.

Content Search

Search across Twitter/X, news, Reddit, YouTube, podcasts, and general web. Use whenever the playbook needs content beyond structured data SDKs — from targeted queries ("what are people saying about NVDA earnings") to broad discovery ("trending crypto discussions this week"), including social discussions, market narratives, news coverage, sentiment, analyst commentary, and community reactions.

Content search modules are called directly in code (not via the partition API). See search.md for per-source SDK usage, enrichment patterns, and gotchas.

4. Altra (Alva Trading Engine)

A feed-based event-driven backtesting engine for quantitative trading strategies. A trading strategy IS a feed: all output data (targets, portfolio, orders, equity, metrics) lives under a single feed's ALFS path. Altra supports historical backtesting and continuous live paper trading, with custom indicators, portfolio simulation, and performance analytics.

5. Deploy on Alva Cloud

Once your data analytics scripts and feeds are ready, deploy them as scheduled cronjobs on Alva Cloud. They run continuously on your chosen schedule (e.g. every hour, every day). All data is private by default; grant public access to specific paths so anyone -- or any playbook page -- can read the data.

User scope enforcement: All write, deploy, and release operations MUST target only the requesting user's namespace. Before any fs/write, draft/playbook, or release/playbook call, verify the target path and username match the authenticated user (from GET /api/v1/me). If you have access to multiple API keys (e.g. from prior sessions), identify the requesting user and scope all operations to that user only. Do NOT write to or release playbooks under other users' namespaces unless the request explicitly asks for cross-user operations (e.g. remix with lineage).

Signal feeds require Altra: Any feed that produces signal/targets or signal/alerts output MUST use FeedAltra. Manual signal construction (building target records without Altra) bypasses bar alignment, portfolio simulation, and look-ahead bias prevention. Use FeedAltra even for simple signal logic — it ensures correct timestamps and prevents forward-looking bugs.

Push notifications for followers: Feeds can produce actionable, subscription-worthy signals that get pushed to playbook followers via Telegram. To make a feed push-capable:

  1. Add a signal/targets output to the feed script (see feed-sdk.md Pattern D) and write signal records using the Altra target format ({date, instruction, meta}), where meta.reason is the human-readable message followers will see.
  2. Set "push_notify": true in the POST /api/v1/deploy/cronjob request, or update the existing cronjob to set "push_notify": true.

The platform reads /data/signal/targets/@last/1 after each successful execution and pushes the signal content to all eligible followers.

See Step 9 below for the full post-release subscription flow.

6. Build the Playbook Web App

After your data pipelines are deployed and producing data, build the playbook's web interface. Create HTML5 pages with Alva Design System that read from Alva's data gateway and visualize the results. Follow the Alva Design System for styling, layout, and component guidelines. Unless the user explicitly asks for a static snapshot, default to a live playbook. Data fetching requirement: Apply the Content Legitimacy Rules when building the UI. All quantitative data in charts, tables, or KPI cards must come from feed outputs read at runtime (no inline literals for data).

7. Release

Common steps (all users)

  1. Write HTML to ALFS: POST /api/v1/fs/write the playbook HTML to ~/playbooks/{name}/index.html.

  2. Create playbook draft: POST /api/v1/draft/playbook — creates DB records, writes draft files and playbook.json to ALFS automatically. This request must include both the URL-safe name and the human-readable display_name. Use [subject/theme] [analysis angle/strategy logic], put the subject/theme first, and keep it within 40 characters. Avoid personal markers such as My, Test, or V2, and generic-only titles such as Stock Dashboard or Trading Bot. Trading symbols: If the playbook involves specific trading assets, include "trading_symbols" in the request — an array of base asset tickers (e.g. ["BTC", "ETH"], ["NVDA", "AAPL"]). The backend resolves each symbol to a full trading pair object and stores the result in the playbook metadata. Max 50 symbols per request. Unknown symbols are silently skipped.

  3. Screenshot: Take a screenshot to verify the playbook renders correctly:

    GET /api/v1/screenshot?url=$ALVA_ENDPOINT/u/<username>/playbooks/<playbook_name>
    

    Pass X-Alva-Api-Key header so the screenshot service can access authenticated content. See screenshot.md for full parameter details.

Pro users (subscription_tier = "pro")

  1. Show draft link: Output the playbook URL — https://alva.ai/u/<username>/playbooks/<playbook_name>. The draft is accessible only to the creator.
  2. Ask: "Your playbook is ready. Would you like to publish it publicly, or keep it private for now?"
    • Publish → call POST /api/v1/release/playbook → output the public URL.
    • Keep private → done. Remind the user that only they can access the draft URL.

Free users (subscription_tier = "free")

  1. Publish directly: Call POST /api/v1/release/playbook — free playbooks are always public. Output the public URL: https://alva.ai/u/<username>/playbooks/<playbook_name>
  2. Upsell only on friction: Do not proactively suggest upgrading. But when the user's experience is degraded because of free-tier limitations — wanting private playbooks, hitting the cronjob cap, resource limits, or any other pro-gated feature — acknowledge the limitation and offer the upgrade path: "This feature is available on the Pro plan. You can upgrade at https://alva.ai/pricing to [specific benefit, e.g. keep playbooks private / deploy more cronjobs / ...]."

Use the playbook name and the username from GET /api/v1/me to construct URLs.

Pre-Release Validation

Before calling POST /api/v1/release/playbook, verify all of the following:

  1. Cronjobs are active: All feeds referenced by the playbook have successfully deployed cronjobs. If deploy/cronjob returned RATE_LIMITED, see Cronjob Rate Limit Recovery below.
  2. HTML fetches from feeds: The playbook HTML reads quantitative data from feed output paths at runtime (not from inline literals), consistent with the Content Legitimacy Rules.
  3. Data is fresh: Read the latest data point from each referenced feed (via @last/1) and check its timestamp. If the latest timestamp is older than 2x the cron interval, warn the user that the playbook will display stale data.
  4. Description is accurate: Update frequency claims match actual cronjob status. Data source claims match actual SDK/BYOD calls in the feed script.
  5. Target user is correct: The playbook is being released under the requesting user's namespace (see user scope enforcement above).

8. Remix (Create from Existing Playbook)

Users can remix any published playbook to create a customized version. The Remix prompt uses the format @{owner}/{name} to identify the source playbook — e.g. Playbook(@alice/btc-momentum). The agent reads the source playbook's feed scripts (strategy logic) and HTML (dashboard UI), customizes them per the user's request, and deploys a new playbook under their own namespace. If the user does not specify what to change, the agent should ask before proceeding.

See remix-workflow.md for the full step-by-step guide.

9. Post-release push notification flow

After a playbook is released or kept as draft (Step 7 complete), proactively evaluate whether any deployed feeds produce push-worthy content. Do not wait for the user to ask.

Identify push-worthy feeds

Scan the feeds backing this playbook and classify each:

  • Push-worthy (recommend): price signals, crossover/breakout alerts, trading instructions, anomaly detection, periodic research summaries — anything actionable and time-sensitive.
  • Not push-worthy (skip): static fundamentals, historical snapshots, low-frequency reference data.

If no feed qualifies, skip this flow entirely.

Check Telegram binding

Read telegram_username from the session (Pre-flight Step 3):

  • Connected (non-null) → proceed to recommend.
  • Not connected (null) → tell the user: "To receive push notifications, connect your Telegram at https://alva.ai/settings. After connecting, I can set up push alerts for [specific feed description]." Then skip the rest of this flow. The user can return to this later.

Recommend specific feeds

Present a concrete recommendation, not a generic "want push?":

"This playbook's BTC EMA crossover signal feed produces actionable alerts when the trend flips. Want to enable Telegram push notifications for it?"

  • User says yes → add signal/targets output to the feed (see feed-sdk.md Pattern D), set push_notify: true on the cronjob, and confirm.
  • User says no → accept and move on. Do not ask again.
  • User requests push for a different feed → honor their choice and configure accordingly.

If the feed already has signal/targets and push_notify: true, skip — it's already configured.


Detailed sub-documents (read these for in-depth reference):

Document Contents
references/api/*.md Split REST API reference docs (user info, filesystem, run, deploy, release, SDK, screenshots, and errors)
jagent-runtime.md Writing jagent scripts: module system, built-in modules, async model, constraints
feed-sdk.md Feed SDK guide: creating data feeds, time series, upstreams, state management
altra-trading.md Altra backtesting engine: strategies, features, signals, testing, debugging
deployment.md Deploying scripts as cronjobs for scheduled execution
design-system.md Alva Design System entry point: tokens, typography, layout; links to widget, component, and playbook specs
remix-workflow.md Remix: create a new playbook from an existing template
adk.md Agent Development Kit: adk.agent() API, tool calling, ReAct loop, examples
search.md Content search SDKs: per-source usage, enrichment patterns, and gotchas for Twitter/X, news, Reddit, YouTube, podcasts, and web
secret-manager.md Secret upload, CRUD API, and runtime usage via require("secret-manager")
skill-trace-finalize.md Skill trace upload (POST .../skill-trace/finalize), aligned with skill_trace_full_reference.md; planning — final step must be finalize

API Reference

Important: Always read the API reference docs before making API requests.

Base URL: $ALVA_ENDPOINT (defaults to https://api-llm.prd.alva.ai).

Examples use HTTP notation (METHOD /path). Auth (X-Alva-Api-Key header) is required on every request unless marked (public, no auth). See Setup above for curl templates.

Reference docs:

Additional endpoints that remain documented inline or in dedicated docs:

  • trading pair search: GET /api/v1/trading-pairs/search?q={q}
  • skill trace finalize: POST /api/v1/skill-trace/finalize

Runtime Modules Quick Reference

Scripts executed via /api/v1/run run in a sandboxed V8 isolate on Alva's servers -- they cannot access the host machine's filesystem, environment variables, or shell. Host-agent permissions still apply. See jagent-runtime.md for full details.

Module require() Description
alfs require("alfs") Filesystem (uses absolute paths /alva/home/<username>/...)
env require("env") userId, username, args from request
secret-manager require("secret-manager") Read user-scoped third-party secrets stored in Alva Secret Manager
net/http require("net/http") fetch(url, init) for async HTTP requests
@alva/algorithm require("@alva/algorithm") Statistics
@alva/feed require("@alva/feed") Feed SDK for persistent data pipelines + FeedAltra trading engine
@alva/adk require("@alva/adk") Agent SDK for LLM requests — agent() for LLM agents with tool calling
@test/suite require("@test/suite") Jest-style test framework (describe, it, expect, runTests)

SDKHub: 250+ data modules available via require("@arrays/crypto/ohlcv:v1.0.0") etc. Version suffix is optional (defaults to v1.0.0). To discover function signatures and response shapes, use the SDK doc API (GET /api/v1/sdk/doc?name=...).

Secret Manager: use const secret = require("secret-manager"); then secret.loadPlaintext("OPENAI_API_KEY"). This returns a string when present or null when the current user has not uploaded that secret.

Key constraints: No top-level await (wrap script in (async () => { ... })();). No Node.js builtins (fs, path, http). Module exports are frozen.


Feed SDK Quick Reference

See feed-sdk.md for full details.

Feeds are persistent data pipelines that store time series data, readable via filesystem paths.

const { Feed, feedPath, makeDoc, num } = require("@alva/feed");
const { getCryptoKline } = require("@arrays/crypto/ohlcv:v1.0.0");
const { indicators } = require("@alva/algorithm");

const feed = new Feed({ path: feedPath("btc-ema") });

feed.def("metrics", {
  prices: makeDoc("BTC Prices", "Close + EMA10", [num("close"), num("ema10")]),
});

(async () => {
  await feed.run(async (ctx) => {
    const raw = await ctx.kv.load("lastDate");
    const lastDateMs = raw ? Number(raw) : 0;

    const now = Math.floor(Date.now() / 1000);
    const start =
      lastDateMs > 0 ? Math.floor(lastDateMs / 1000) : now - 30 * 86400;

    const bars = getCryptoKline({
      symbol: "BTCUSDT",
      start_time: start,
      end_time: now,
      interval: "1h",
    })
      .response.data.slice()
      .reverse();
    const closes = bars.map((b) => b.close);
    const ema10 = indicators.ema(closes, { period: 10 });

    const records = bars
      .map((b, i) => ({
        date: b.date,
        close: b.close,
        ema10: ema10[i] || null,
      }))
      .filter((r) => r.date > lastDateMs);

    if (records.length > 0) {
      await ctx.self.ts("metrics", "prices").append(records);
      await ctx.kv.put("lastDate", String(records[records.length - 1].date));
    }
  });
})();

Feed output is readable at: ~/feeds/btc-ema/v1/data/metrics/prices/@last/100


Data Modeling Patterns

All data produced by a feed should use feed.def() + ctx.self.ts().append(). Do not use alfs.writeFile() for feed output data.

Pattern A -- Snapshot (latest-wins): For data that represents current state (company detail, ratings, price target consensus). Use start-of-day as the date so re-runs overwrite.

const today = new Date();
today.setHours(0, 0, 0, 0);
await ctx.self
  .ts("info", "company")
  .append([
    { date: today.getTime(), name: company.name, sector: company.sector },
  ]);

Read @last/1 for current snapshot, @last/30 for 30-day history.

Pattern B -- Event log: For timestamped events (insider trades, news, senator trades). Each event uses its natural date. Same-date records are auto-grouped.

const records = trades.map((t) => ({
  date: new Date(t.transactionDate).getTime(),
  name: t.name,
  type: t.type,
  shares: t.shares,
}));
await ctx.self.ts("activity", "insiderTrades").append(records);

Pattern C -- Tabular (versioned batch): For data where the whole set refreshes each run (top holders, EPS estimates). Stamp all records with the same run timestamp; same-date grouping stores them as a batch.

const now = Date.now();
const records = holdings.map((h, i) => ({
  date: now,
  rank: i + 1,
  name: h.name,
  marketValue: h.value,
}));
await ctx.self.ts("research", "institutions").append(records);
Data Type Pattern Date Strategy Read Query
OHLCV, indicators Time series (standard) Bar timestamp @last/252
Company detail, ratings Snapshot (A) Start of day @last/1
Insider trades, news Event log (B) Event timestamp @last/50
Holdings, estimates Tabular (C) Run timestamp @last/N

See feed-sdk.md for detailed data modeling examples and deduplication behavior.


Deploying Feeds

Every feed follows a 6-step lifecycle including every newly created feed or re-created feed:

  1. Write -- define schema + incremental logic with ctx.kv

  2. Upload -- write script to ~/feeds/<name>/v1/src/index.js

  3. Test -- POST /api/v1/run with entry_path to verify output

  4. Grant -- make feed data publicly readable:

    POST /api/v1/fs/grant
    {"path":"~/feeds/<name>","subject":"special:user:*","permission":"read"}
    

    Grant on the feed root path (not on data/). Subject format: special:user:* (public), special:user:+ (authenticated only), user:<id> (specific user).

  5. Deploy -- POST /api/v1/deploy/cronjob for scheduled execution

  6. Release -- POST /api/v1/release/feed to register the feed in the database (requires the cronjob_id from the deploy step)

Data Type Recommended Schedule Rationale
Stock OHLCV + technicals 0 */4 * * * (every 4h) Markets update during trading hours
Company detail, price targets 0 8 * * * (daily 8am) Changes infrequently
Insider/senator trades 0 8 * * * (daily 8am) SEC filings are daily
Earnings estimates 0 8 * * * (daily 8am) Updated periodically

See deployment.md for the full deployment guide and API reference.


Error Transparency

When SDK modules fail or are unavailable, you MUST be transparent with the user. Do not silently fall back to inferior data sources.

Pro / Subscription-Gated SDKs

When an SDK module returns a Pro-only or subscription error:

  1. Inform the user which module is unavailable and why (subscription tier).
  2. Explain what capability is lost (e.g. "senator trading data requires Pro — this playbook won't include congressional trading activity").
  3. If falling back to an alternative source, clearly state what the fallback is and its limitations (e.g. "Using web search as fallback — data may be incomplete or unverified").
  4. Never silently substitute with LLM-fabricated data.

Coverage Limitations

When the user requests data outside Alva's supported asset classes (e.g. forex pairs, which are not in SDKHub), state the limitation upfront rather than discovering it through failed searches. Suggest BYOD alternatives if a public API exists.


Debugging Feeds

Resetting Feed Data (development only)

During development, use the REST API to clear stale or incorrect data. Do not use this in production.

# Clear a specific time series output
DELETE /api/v1/fs/remove?path=~/feeds/my-feed/v1/data/market/ohlcv&recursive=true

# Clear an entire group (all outputs under "market")
DELETE /api/v1/fs/remove?path=~/feeds/my-feed/v1/data/market&recursive=true

# Full reset: clear ALL data + KV state (removes the data mount, re-created on next run)
DELETE /api/v1/fs/remove?path=~/feeds/my-feed/v1/data&recursive=true

Inline Debug Snippets

Test SDK shapes before building a full feed:

POST /api/v1/run
{"code":"const { getCryptoKline } = require(\"@arrays/crypto/ohlcv:v1.0.0\"); JSON.stringify(Object.keys(getCryptoKline({ symbol: \"BTCUSDT\", start_time: 0, end_time: 0, interval: \"1h\" })));"}

Skill trace upload

For any turn that uses this skill and should be persisted for future reference, include a brief note in the plan that the trace will be uploaded according to skill-trace-finalize.md.

This is mainly so the turn can be referenced and audited later when needed, including lightweight one-off lookups that may still be worth preserving.

Before the final user-visible answer, call POST /api/v1/skill-trace/finalize once to upload the trace. You must read reference skill-trace-finalize.md before calling the API.


Secret Manager

Use Alva Secret Manager whenever a playbook or runtime script needs a third-party credential such as an LLM API key, search token, exchange key, or webhook secret.

  • Preferred upload path: ask the user to add or edit the secret in the web UI at https://alva.ai/apikey. Assume this page is available.
  • Do not ask the user to paste sensitive third-party secrets into chat when the web upload flow is feasible.
  • Do not hardcode secrets in source code, ALFS files, .env, shell snippets, or released playbook assets.
  • Runtime access: load secrets inside Alva Cloud code with require("secret-manager").loadPlaintext("NAME").
  • loadPlaintext(name) returns the plaintext string when present, or null when the secret is missing for the current user.
  • If a required secret is missing, stop and tell the user exactly which secret name to upload at https://alva.ai/apikey.
  • For agent-managed setup, inspection, or cleanup, authenticated CRUD endpoints are available under /api/v1/secrets.

Read secret-manager.md whenever the task involves uploading, naming, rotating, listing, or using third-party secrets.


Altra Trading Engine Quick Reference

Always use Altra for backtesting. Altra handles bar.endTime timestamps, data alignment, and portfolio simulation automatically. Do not manually loop over SDK data (e.g. getCryptoKline) to evaluate trading conditions — this leads to incorrect timestamps and look-ahead bias. Use Altra even for simple strategies; it supports any interval ("1min" to "1w") and any combination of OHLCV + external data via registerRawData.

After a successful backtest, you should package the results in a form the user can use. That may be a playbook, a dashboard, or a concise analytical summary, depending on the request. A backtest that only prints raw console output is usually incomplete — see Request Routing above.

See altra-trading.md for full details.

const { createOHLCVProvider } = require("@arrays/data/ohlcv-provider:v1.0.0");
const { FeedAltraModule } = require("@alva/feed");
const { FeedAltra, e, Amount } = FeedAltraModule;

const altra = new FeedAltra(
  {
    path: "~/feeds/my-strategy/v1",
    startDate: Date.parse("2025-01-01T00:00:00Z"),
    portfolioOptions: { initialCash: 1_000_000 },
    simOptions: { simTick: "1min", feeRate: 0.001 },
    perfOptions: { timezone: "UTC", marketType: "crypto" },
  },
  createOHLCVProvider(),
);

const dg = altra.getDataGraph();
dg.registerOhlcv("BINANCE_SPOT_BTC_USDT", "1d"); // any interval: "1min" to "1w"
dg.registerFeature({ name: "rsi" /* ... */ });

altra.setStrategy(strategyFn, {
  trigger: { type: "events", expr: e.ohlcv("BINANCE_SPOT_BTC_USDT", "1d") },
  inputConfig: {
    ohlcvs: [{ id: { pair: "BINANCE_SPOT_BTC_USDT", interval: "1d" } }],
    features: [{ id: "rsi" }],
  },
  initialState: {},
});

(async () => {
  await altra.run(Date.now());
})();

ADK (Agent Development Kit) Quick Reference

See adk.md for the full API, tool-calling patterns, memory patterns, and implementation examples.

ADK is a universal agent development kit that runs inside the Jagent V8 runtime. Use it to build LLM-powered agents that can reason over tasks, call tools, gather context from multiple sources, and return structured outputs.

It is best suited for workflows where the "thinking" step cannot be expressed as pure deterministic code, such as research synthesis, document analysis, classification, and summarization over real upstream data.

When to Use ADK

Use ADK when you need an agent to:

  • Fetch real data through tools, APIs, SDKs, or files
  • Reason over multiple inputs before producing an answer
  • Synthesize findings into structured notes, summaries, or classifications
  • Power periodic research or analysis workflows that run on a schedule
  • Add an LLM-driven transformation step inside a larger data pipeline

When NOT to Use ADK

ADK must never be used to fabricate data that should come from real sources. Specifically:

  • Do NOT use ADK to generate hiring statistics, financial events, analyst reports, or any quantitative data that claims to originate from a real data pipeline.
  • Do NOT present ADK-generated content as if it were sourced from SDKs, APIs, or databases.
  • If a data source is unavailable, report the limitation as a blocker — do not use ADK as a fallback data generator.

ADK output that involves reasoning over real data (sentiment classification, trend summarization) is fine, but must be labeled as AI-generated analysis.


Deployment Quick Reference

See deployment.md for full details.

Deploy feed scripts or tasks as cronjobs for scheduled execution:

POST /api/v1/deploy/cronjob
{"path":"~/feeds/btc-ema/v1/src/index.js","cron_expression":"0 */4 * * *","name":"btc-ema-update"}

Cronjobs execute the script via the same jagent runtime as /api/v1/run. Max 20 cronjobs per user. Min interval: 1 minute.

Name format: All resource names (cronjobs, feeds, playbooks) must be 1–63 lowercase alphanumeric characters or hyphens, and cannot start or end with a hyphen (DNS label format). Example: btc-ema-update, not BTC EMA Update.

After deploying a cronjob, register the feed, create a playbook draft, then release the playbook for public hosting. The playbook HTML must already be written to ALFS at ~/playbooks/{name}/index.html via fs/write before releasing.

Important: Feed names and playbook names must be unique within your user space. Before creating a new feed or playbook, use GET /api/v1/fs/readdir?path=~/feeds or GET /api/v1/fs/readdir?path=~/playbooks to check for existing names and avoid conflicts.

# 1. Release feed (register in DB, link to cronjob)
POST /api/v1/release/feed
{"name":"btc-ema","version":"1.0.0","cronjob_id":42}
→ {"feed_id":100,"name":"btc-ema","feed_major":1}

# 2. Create playbook draft (creates DB record + ALFS draft files automatically)
#    Include trading_symbols when the playbook involves specific assets.
POST /api/v1/draft/playbook
{"name":"btc-dashboard","display_name":"BTC Trend Dashboard","description":"BTC market dashboard","feeds":[{"feed_id":100}],"trading_symbols":["BTC"]}
→ {"playbook_id":99,"playbook_version_id":200}

# 3. Release playbook (reads HTML from ALFS, uploads to CDN, writes release files automatically)
POST /api/v1/release/playbook
{"name":"btc-dashboard","version":"v1.0.0","feeds":[{"feed_id":100}]}
→ {"playbook_id":99,"version":"v1.0.0","published_url":"https://alice.playbook.alva.ai/btc-dashboard/v1.0.0/index.html"}

# After release, output the alva.ai playbook link to the user:
# https://alva.ai/u/<username>/playbooks/<playbook_name>
# e.g. https://alva.ai/u/alice/playbooks/btc-dashboard

Alva Design System

All Alva playbook pages, dashboards, and widgets must follow the Alva Design System. Start with design-system.md: it is the single global entry point for tokens, typography, page-level layout rules, and the reading path to the more detailed design references.

Read only what you need:


Filesystem Layout Convention

Path Purpose
~/tasks/<name>/src/ Task source code
~/feeds/<name>/v1/src/ Feed script source code
~/feeds/<name>/v1/data/ Feed synth mount (auto-created by Feed SDK)
~/playbooks/<name>/ Playbook web app assets
~/data/ General data storage
~/library/ Shared code modules

Prefer using the Feed SDK for all data organization, including point-in-time snapshots. Store snapshots as single-record time series rather than raw JSON files via alfs.writeFile(). This keeps all data queryable through a single consistent read pattern (@last, @range, etc.).


Common Pitfalls

  • @last returns chronological (oldest-first) order, consistent with @first and @range. No manual sorting needed.
  • Time series reads return flat JSON records. Paths with @last, @range, etc. return JSON arrays of flat records like [{"date":...,"close":...,"ema10":...}]. Regular paths return file content with Content-Type: application/octet-stream.
  • last(N) limits unique timestamps, not records. When multiple records share a timestamp (grouped via append()), auto-flatten may return more than N individual records.
  • The data/ in feed paths is the synth mount. feedPath("my-feed") gives ~/feeds/my-feed/v1, and the Feed SDK mounts storage at <feedPath>/data/. Don't name your group "data" or you'll get data/data/....
  • Public reads require absolute paths. Unauthenticated reads must use /alva/home/<username>/... (not ~/...). Discover your username via GET /api/v1/me.
  • Top-level await is not supported. Wrap async code in (async () => { ... })();.
  • require("alfs") uses absolute paths. Inside the V8 runtime, alfs.readFile() needs full paths like /alva/home/alice/.... Get your username from require("env").username.
  • No Node.js builtins. require("fs"), require("path"), require("http") do not exist. Use require("alfs") for files, require("net/http") for HTTP.
  • Altra run() is async. FeedAltra.run() returns a Promise<RunResult>. Always await it: const result = await altra.run(endDate);
  • Altra lookback: feature vs strategy. Feature lookback controls how many bars the feature computation sees. Strategy lookback controls how many feature outputs the strategy function sees. They are independent.
  • Home directory not provisioned? If you get PERMISSION_DENIED on all ALFS operations (including ~/), your home directory was not created during sign-up. Call POST /api/v1/fs/ensure-home (no body needed, uses your auth token) to provision it. This is idempotent and safe to call anytime.
  • Cronjob path must point to an existing script. The deploy API validates the entry_path exists via filesystem stat before creating the cronjob.
  • Always create a draft before releasing. POST /api/v1/release/playbook requires the playbook to already exist (created via POST /api/v1/draft/playbook).
  • Create new playbooks from scratch unless you are doing a version update. Only version updates may refer to an existing playbook. For all other new playbooks, do not read existing ones.
  • ECharts: use type: 'time' for date axes. Do not pass raw epoch millisecond values as category labels — users will see numbers like 1773840600000 instead of dates. Use type: 'time' axis, which handles formatting automatically, or format dates before passing to a category axis.
  • ECharts graph: validate node/edge data. For type: 'graph' series with layout: 'none', verify every edge source/target matches an existing node name, no duplicate node names exist, and node names don't contain special characters that break ECharts internals. Add a try/catch wrapper around chart initialization with a fallback message if rendering fails.
  • ECharts sizing: allocate sufficient height. Heatmaps need height = max(300px, numRows * 40px). Primary charts on overview tabs should be at least 400px tall and visually dominant over KPI cards. Do not compress charts to fit everything above the fold.
  • Separate lastDate watermarks per data source. When a feed combines multiple data sources with different update frequencies (e.g. ETF OHLCV + VIX + CPI), use a separate ctx.kv key for each source's watermark (e.g. lastDate_etf, lastDate_vix, lastDate_cpi). A shared watermark causes slower-updating sources to be permanently filtered out after the first run.

Resource Limits

Resource Limit
V8 heap per execution 2 GB
Write payload 10 MB max per request
HTTP response body 128 MB max
Max cronjobs per user 20
Min cron interval 1 minute
general reviews

Ratings

4.510 reviews
  • Shikha Mishra· Oct 10, 2024

    alva is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.

  • Piyush G· Sep 9, 2024

    Keeps context tight: alva is the kind of skill you can hand to a new teammate without a long onboarding doc.

  • Chaitanya Patil· Aug 8, 2024

    Registry listing for alva matched our evaluation — installs cleanly and behaves as described in the markdown.

  • Sakshi Patil· Jul 7, 2024

    alva reduced setup friction for our internal harness; good balance of opinion and flexibility.

  • Ganesh Mohane· Jun 6, 2024

    I recommend alva for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.

  • Oshnikdeep· May 5, 2024

    Useful defaults in alva — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.

  • Dhruvi Jain· Apr 4, 2024

    alva has been reliable in day-to-day use. Documentation quality is above average for community skills.

  • Rahul Santra· Mar 3, 2024

    Solid pick for teams standardizing on skills: alva is focused, and the summary matches what you get after install.

  • Pratham Ware· Feb 2, 2024

    We added alva from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.

  • Yash Thakker· Jan 1, 2024

    alva fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.