Skip to content

haakoan/astroagent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AstroAgent

A Claude-powered triage pipeline for time-domain astronomy. AstroAgent fetches transient alerts from ZTF brokers (Fink, Lasair, ANTARES), enriches them with catalog crossmatches (SIMBAD, NED, TNS), applies physics-motivated filters, and stores candidates in a local SQLite database. Claude Code drives the pipeline end to end — you describe what you're looking for in plain language, and Claude decides what to query, how to filter, and how to interpret the results.

A web dashboard is included for browsing candidates, viewing light curves, and inspecting filters.


What's in the box

  • CLI (astroagent) — query brokers, enrich, filter, list candidates
  • Web dashboard (astroagent-web) — Dash-based UI with filter cards, sky maps, magnitude histograms, light curve viewer, and per-filter source code inspection
  • Plotting (astroagent-plot) — static matplotlib dashboards
  • Filter system — physics-motivated Python filters that can be hand-written or Claude-generated from natural language; auto-loaded from astroagent/filters/generated/
  • CLAUDE.md — the agent's operating manual; loaded automatically when you run Claude Code in this directory

Installation

Prerequisites

  • Python ≥ 3.10
  • A working git and pip
  • (Recommended) Claude Code installed and authenticated

1. Clone and install

git clone https://github.com/<your-org>/astroagent.git
cd astroagent

# Create a virtualenv (recommended)
python3 -m venv .venv
source .venv/bin/activate    # bash/zsh
# source .venv/bin/activate.fish    # fish

pip install -e .

This installs three command-line entry points:

  • astroagent — main CLI
  • astroagent-web — Dash web dashboard
  • astroagent-plot — static matplotlib plots

2. Configure API keys

cp .env.example .env

Then edit .env and fill in:

Variable Required for Where to get it
LASAIR_TOKEN Lasair broker https://lasair-ztf.lsst.ac.uk → register, then profile
ANTARES_API_KEY ANTARES broker https://antares.noirlab.edu → register
TNS_API_KEY, TNS_BOT_ID, TNS_BOT_NAME TNS crossmatch (optional) https://www.wis-tns.org/bots

Fink requires no authentication. SIMBAD and NED also require no keys.

3. Verify the installation

astroagent health

You should see something like:

  ✓ fink       Reachable. Got 0 test result(s).
  ✓ lasair     Reachable. Got 1 test result(s).
  ✗ antares    No ANTARES_API_KEY set — skipping.

ANTARES will be skipped if you didn't set its key — that's fine, the other two brokers provide enough coverage for most workflows.


Usage

Driving the pipeline with Claude Code

The intended workflow is to launch Claude Code inside this repository and ask it questions in natural language:

cd astroagent
claude

Then prompt it like:

> Find tidal disruption event candidates from the last 90 days, apply all filters,
  and tell me which ones survived.

> My coworker is interested in extragalactic transients in galaxies — anything still
  active in the last 3 months. Can you build a filter for this?

> Open the web dashboard so I can browse what we found.

Claude reads CLAUDE.md automatically and understands the full CLI surface and the filter system. It will check the API budget first, query the brokers, run the filters, and report back.

CLI quick reference

# Check API budget — always run this first
astroagent usage --json

# Query a broker by class (auto-saved to the store)
astroagent query fink class --class-name TDE --days-back 90 --max-results 30 --json

# Apply all filters to everything in the store
astroagent filter --all-stored --json

# List candidates that passed a filter
astroagent candidates list --filter-passed tde --json

# Show full details for one candidate
astroagent candidates show ZTF25acgtfmh --json

# Enrich with catalog crossmatches (SIMBAD, NED, optionally TNS)
astroagent enrich ZTF25acgtfmh --no-tns --json

# Register a custom filter from a .py file
astroagent filters load /path/to/my_filter.py

See CLAUDE.md for the full command reference.

Web dashboard

astroagent-web              # http://localhost:8050
astroagent-web --port 8080  # custom port

The landing page shows a card per filter with the natural-language description that motivated the filter. Click a card to drill into that filter's candidates: sky map, magnitude histogram, sortable table, and light curves on demand. Each dashboard page also has a "View filter source code" panel and a "↻ Refresh Data" button to re-query brokers and re-apply filters.

If the most recent data is more than a day old, the dashboard auto-refreshes when you click into a filter.

Static plots

astroagent-plot                                          # all stored candidates
astroagent-plot --filter-passed extragalactic -o out.png # only passed candidates

Writing your own filter

A filter is a Python class subclassing BaseFilter. Drop a file in astroagent/filters/generated/ and it gets auto-loaded at startup. Or load it ad hoc with astroagent filters load <path>.

# astroagent/filters/generated/my_kilonova.py
from astroagent.filters.base import BaseFilter, FilterResult
from astroagent.schema import Alert


class KilonovaFilter(BaseFilter):
    name = "kilonova"
    description = "Fast-rising, rapidly-reddening transients consistent with kilonovae."
    project_text = (
        "Find kilonova candidates: fast (< 2 day) rise time, rapidly reddening colour, "
        "and faint (peak r > 18). Based on Andreoni+2020 selection criteria."
    )

    def run(self, alert: Alert) -> FilterResult:
        if alert.duration_days is not None and alert.duration_days > 2.0:
            return FilterResult(passed=False, reason=f"Too slow: {alert.duration_days:.1f}d")

        # ... your selection logic here ...

        return FilterResult(passed=True, reason="Consistent with KN timescale")

The project_text field is what gets shown on the web dashboard's filter card and the "science goal" box on the dashboard page. Use it to capture the plain-language reasoning behind the filter so future-you (or your coworkers) understand what the page is for.

See astroagent/filters/builtin/tde.py for a richer example.


Project layout

astroagent/
├── astroagent/
│   ├── cli.py             # Click CLI entry point
│   ├── webapp.py          # Dash web dashboard
│   ├── plotting.py        # Static matplotlib plots
│   ├── schema.py          # Alert + PhotoPoint dataclasses
│   ├── brokers/           # FinkBroker, LasairBroker, AntaresBroker
│   ├── filters/
│   │   ├── base.py        # BaseFilter, FilterRegistry
│   │   ├── builtin/       # quality, galactic_plane, tde
│   │   └── generated/     # auto-loaded user/Claude filters
│   ├── enrichment/        # SIMBAD, NED, TNS crossmatch
│   ├── memory/            # SQLite store + API usage tracker
│   └── config/
├── CLAUDE.md              # Agent operating manual (read by Claude Code)
├── pyproject.toml
├── .env.example
└── README.md

The candidate store and API usage history live in ~/.astroagent/candidates.db by default. Override with ASTROAGENT_DB=/path/to/db in .env.


Known limitations

  • TDE filter is conservative: it requires multiple detections and rejects anything broker-tagged as AGN. Run astroagent enrich on candidates first to give it crossmatch data — without that, the host-galaxy and TNS checks are skipped.
  • Webapp loading is slow for large stores (a few seconds per dashboard page) because it currently shells out to the CLI per candidate. A direct-store loader is on the to-do list.
  • No automated tests yet — verify changes by running astroagent health and spot-checking with the webapp.
  • Fink/Lasair APIs change without notice. If queries start failing, check astroagent/brokers/fink.py::FINK_CLASS_MAP and astroagent/brokers/lasair.py::LASAIR_BASE first.

Contributing

This is a research prototype. If you build a useful filter, drop it in astroagent/filters/generated/ and open a PR — we'll move the good ones to astroagent/filters/builtin/ over time.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages