{"id":51042322,"url":"https://github.com/MotleyAI/slayer","last_synced_at":"2026-07-10T13:00:54.687Z","repository":{"id":345486026,"uuid":"1184045599","full_name":"MotleyAI/slayer","owner":"MotleyAI","description":"SLayer: a lightweight semantic layer for AI agents and humans","archived":false,"fork":false,"pushed_at":"2026-07-02T11:49:25.000Z","size":11392,"stargazers_count":118,"open_issues_count":4,"forks_count":14,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-07-02T12:04:39.373Z","etag":null,"topics":["semantic-layer"],"latest_commit_sha":null,"homepage":"https://motley.ai/slayer","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MotleyAI.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-17T07:40:08.000Z","updated_at":"2026-07-02T11:47:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"cf9dadce-3029-45ac-9053-890ef5aa0d34","html_url":"https://github.com/MotleyAI/slayer","commit_stats":null,"previous_names":["motleyai/slayer"],"tags_count":35,"template":false,"template_full_name":null,"purl":"pkg:github/MotleyAI/slayer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MotleyAI%2Fslayer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MotleyAI%2Fslayer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MotleyAI%2Fslayer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MotleyAI%2Fslayer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MotleyAI","download_url":"https://codeload.github.com/MotleyAI/slayer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MotleyAI%2Fslayer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35331955,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-10T02:00:06.465Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["semantic-layer"],"created_at":"2026-06-22T12:00:19.532Z","updated_at":"2026-07-10T13:00:54.677Z","avatar_url":"https://github.com/MotleyAI.png","language":"Python","funding_links":[],"categories":["1. Core Frameworks \u0026 Libraries"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/MotleyAI/slayer/main/docs/images/slayer-hero.png\" alt=\"SLayer — AI agent operating a semantic layer\" width=\"600\"\u003e\n\u003c/p\u003e\n\n[![PyPI](https://img.shields.io/pypi/v/motley-slayer?label=PyPI)](https://pypi.org/project/motley-slayer/)\n[![Python](https://img.shields.io/pypi/pyversions/motley-slayer)](https://pypi.org/project/motley-slayer/)\n[![Docs](https://img.shields.io/badge/docs-docs.motley.ai-blue)](https://docs.motley.ai/slayer/)\n[![License](https://img.shields.io/github/license/MotleyAI/slayer)](LICENSE)\n[![GitHub stars](https://img.shields.io/github/stars/MotleyAI/slayer?style=social)](https://github.com/MotleyAI/slayer/stargazers)\n[![Discord](https://img.shields.io/badge/Discord-join-5865F2?logo=discord\u0026logoColor=white)](https://discord.gg/egWxMctHCA)\n\n**SLayer** is a lightweight semantic layer and query engine.\n\nDefine fields and metrics you need in data models, link your context, and query semantically; SLayer generates and runs the SQL across any database, for any surface: AI agents, dashboards, notebooks. Python-embeddable or standalone (CLI, MCP, API server).\n\n### What you can do with SLayer\n\n- **Allow your team to self-serve analytics** — model your metrics once and let anyone (or their AI agents, over MCP) ask questions, with answers grounded in your definitions and business context instead of the LLM's guesses.\n- **Embed on-demand analytics into your app** — turn agent-generated query specs into safe, executed SQL, with row-level security so each user sees only what they're allowed to.\n- **Load data from SQL databases to Python semantically** — point SLayer at them, and you don't have to build any SQL-translation logic. It generates and translates SQL across Postgres, MySQL, Snowflake, BigQuery, and more; returns clean dataframes. Import the library and use it in-process.\n\n\u003e If you find SLayer useful, a ⭐ helps others discover it!\n\u003e Questions, ideas, or feedback? [Join our Discord](https://discord.gg/egWxMctHCA).\n\n---\n\n## How it works\n\nSLayer sits between your databases and whatever consumes the data — AI agents, internal tools, dashboards, scripts. It lets you:\n\n- Auto-generate data models from your database schema (warm start)\n- Query through a [structured API](https://docs.motley.ai/slayer/concepts/queries/) of measures, dimensions, and filters\n- Choose aggregations [at query time, not in the models](https://docs.motley.ai/slayer/examples/07_aggregations/aggregations/)\n- Create or edit models at runtime and use them immediately — by hand, from your app, or by an agent\n- Save and retrieve natural-language memories about your data and queries\n- Run in-process as a Python library, or standalone via CLI, MCP, or API server\n\nBecause models are editable at runtime, your semantic layer can grow with use: when a query needs a new measure, you (or an agent) add it once and reuse it everywhere.\n\nSLayer compiles queries into the correct SQL for your database, handling joins, aggregations, time-based calculations, and dialect differences. Its DSL is very expressive, [supporting](https://docs.motley.ai/slayer/examples/04_time/time/) queries like _\"month-on-month % increase in total revenue, compared to the previous year\"_, [queries-as-models](https://docs.motley.ai/slayer/examples/06_multistage_queries/multistage_queries/) and much more.\n\nSLayer exposes [MCP](https://github.com/MotleyAI/slayer?tab=readme-ov-file#mcp-server), [REST API](https://github.com/MotleyAI/slayer?tab=readme-ov-file#rest-api), [CLI](https://github.com/MotleyAI/slayer?tab=readme-ov-file#cli), [Python](https://github.com/MotleyAI/slayer?tab=readme-ov-file#python-client), [Flight SQL](https://docs.motley.ai/slayer/interfaces/flight-sql/) (JDBC, BI-tool compatible), and a [Postgres facade](https://docs.motley.ai/slayer/interfaces/pg-facade/) (point any BI dashboard's Postgres connector at SLayer) interfaces and [supports](https://docs.motley.ai/slayer/configuration/datasources/#supported-database-types) most popular databases.\n\n### Example\n\nQuestion (run on the built-in demo Jaffle Shop database): **\"show monthly revenue by store, with month-over-month % change\"**\n\nSide by side, here's LLM-generated SQL and the equivalent SLayer query.\n\n![Example SQL vs SLayer query](https://github.com/user-attachments/assets/a8c73688-e760-402e-9f87-a05591d6cbee)\n\n\n## Quickstart\n\nWe recommend using [uv](https://docs.astral.sh/uv/), especially if you don't work in a Python project.\n```bash\nuv tool install 'motley-slayer[all]'\n```\n\nIf `slayer` isn't found on PATH afterwards, run `uv tool update-shell` and reopen your terminal.\n\n### Using demo dataset\n```bash\n# With the Jaffle Shop demo preloaded (zero-config quickstart)\nclaude mcp add slayer_demo -- slayer mcp --demo\n```\n\n### Using your own data\nSet up your datasource, substituting the correct database, username, hostname, and db_name.\n\n```bash\nslayer datasources create 'postgresql://user:${DB_PASSWORD}@hostname/db_name'\n```\n\nThe password will be read by SLayer at init time, not saved to disk nor exposed to Claude.\n\nThen add SLayer to Claude Code:\n\n```bash\nclaude mcp add slayer -- slayer mcp --ingest-on-startup\n```\n\nNow SLayer MCP will be visible in Claude Code next time you start it. Make sure to launch Claude Code from a shell where `DB_PASSWORD` is exported — the MCP subprocess inherits its environment from the launching process.\n\nRead more on how to get started with [MCP](https://docs.motley.ai/slayer/getting-started/mcp/), [CLI](https://docs.motley.ai/slayer/getting-started/cli/), [REST API](https://docs.motley.ai/slayer/getting-started/rest-api/), [Python](https://docs.motley.ai/slayer/getting-started/python/) in the docs.\n\n\n### Known limitations\n\nSLayer currently has no caching or pre-aggregation engine. This could affect performance for high-concurrency use cases or with large datasets.\nAdding a caching layer is on the [roadmap](https://github.com/MotleyAI/slayer?tab=readme-ov-file#roadmap).\n\n\n## Interfaces\n\n### MCP Server\n\nSLayer supports two MCP transports, **HTTP** (served alongside the API) and **stdio** (serverless, spawned by the agent). Using Claude Code:\n\n```bash\n# 1. stdio-based, does not require a running server\nclaude mcp add slayer -- slayer mcp\n\n# 1b. same, but preload the Jaffle Shop demo on startup\nclaude mcp add slayer -- slayer mcp --demo\n\n# 1c. same, but run idempotent auto-ingestion across every configured datasource on startup\nclaude mcp add slayer -- slayer mcp --ingest-on-startup\n\n# 2. HTTP-based (SSE), provided SLayer server is already running\nclaude mcp add slayer-remote --transport sse --url http://localhost:5143/mcp/sse\n```\n\nSLayer **does not expose credentials** to consumers once created.\n\nBoth transports expose the same tools, allowing to inspect, create and update datasources and models and run queries. More info in the [docs](https://docs.motley.ai/slayer/reference/mcp/).\n\n\n### CLI\n\nSlayer exposes a rich CLI:\n\n```bash\n# Show help\nslayer\n\n# Run a query directly from the terminal\nslayer query '{\"source_model\": \"orders\", \"measures\": [\"*:count\"], \"dimensions\": [\"status\"]}'\n\n# Or from a file\nslayer query @query.json --format json\n```\n\nThese commands do not depend on a running server. See more in the [docs](https://docs.motley.ai/slayer/reference/cli/).\n\n### Python Client\n\nUseful for agents working in code execution environments, e.g. for AI data analytics, as well as any Python apps.\n\n```python\nfrom slayer.client.slayer_client import SlayerClient\nfrom slayer.core.query import SlayerQuery\n\n# Remote mode (connects to running server)\nclient = SlayerClient(url=\"http://localhost:5143\")\n\n# Or local mode (no server needed)\nfrom slayer.storage.yaml_storage import YAMLStorage\nclient = SlayerClient(storage=YAMLStorage(base_dir=\"./my_models\"))\n\n# Query data\nquery = SlayerQuery(\n    source_model=\"orders\",\n    measures=[\"*:count\", \"revenue:sum\"],\n    dimensions=[\"status\"],\n    limit=10,\n)\ndf = client.query_df(query)\nprint(df)\n```\n\nSee more in the [docs](https://docs.motley.ai/slayer/reference/python-client/).\n\n### REST API\n\n```bash\n# Query\ncurl -X POST http://localhost:5143/query \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"source_model\": \"orders\", \"measures\": [\"*:count\"], \"dimensions\": [\"status\"]}'\n\n# List models (returns name + description)\ncurl http://localhost:5143/models\n\n# Get a single datasource (credentials masked)\ncurl http://localhost:5143/datasources/my_postgres\n```\n\nSee more in the [docs](https://docs.motley.ai/slayer/reference/rest-api/).\n\n### BI Dashboards\n\nView your SLayer models from any BI tool — no Java or custom driver needed. Start the Postgres facade and point a dashboard's **PostgreSQL** connector at it:\n\n```bash\n# Start SLayer speaking the Postgres wire protocol (Jaffle Shop demo).\n# Containerized BI tools connect over the network, so bind all interfaces\n# (non-loopback binds require a token).\nslayer pg-serve --demo --host 0.0.0.0 --token pick-a-secret\n\n# Run the BI tool with host.docker.internal mapped to the Docker host\n# (built into Docker Desktop; the flag makes it work on Linux too). The\n# volume keeps Metabase's settings/dashboards across container re-creates.\ndocker run -d -p 3000:3000 --name metabase \\\n  --add-host=host.docker.internal:host-gateway \\\n  -e MB_DB_FILE=/metabase.data/metabase.db \\\n  -v metabase-data:/metabase.data \\\n  metabase/metabase\n\n# Metabase: Add database -\u003e PostgreSQL\n#   host=host.docker.internal  port=5145  database=jaffle_shop\n#   user=anything  password=pick-a-secret  SSL=off\n```\n\nThe connection's `database` selects the SLayer datasource; its models appear as tables under schema `public`. There's also an [Arrow Flight SQL](https://docs.motley.ai/slayer/interfaces/flight-sql/) facade for JDBC clients. See the [Postgres facade docs](https://docs.motley.ai/slayer/interfaces/pg-facade/) for auth, TLS, and the supported SQL surface.\n\n\n\n## Models\n\nBy default, models are defined as YAML files. Add an optional `description` to help users and agents understand complex models:\n\n```yaml\nname: orders\nsql_table: public.orders\ndata_source: my_postgres\ndescription: \"Core orders table with revenue metrics\"\n\n# A single `columns` list — every column can be used as a group-by key\n# OR as the input to a query-time aggregation, gated by type/PK rules.\ncolumns:\n  - name: id\n    sql: id\n    type: number\n    primary_key: true\n  - name: status\n    sql: status\n    type: string\n  - name: created_at\n    sql: created_at\n    type: time\n  - name: revenue\n    sql: amount\n    type: number\n  - name: quantity\n    sql: qty\n    type: number\n\n# Optional library of named formulas that queries can reference by bare name.\nmeasures:\n  - name: aov\n    formula: \"revenue:sum / *:count\"\n    label: \"Average Order Value\"\n```\n\n## Measures\n\nThe `measures` parameter on a query specifies what data columns to return. Aggregations are picked at query time via colon syntax (`revenue:sum`, `*:count`); transforms wrap them (`cumsum(revenue:sum)`).\n\n```json\n{\n  \"source_model\": \"orders\",\n  \"dimensions\": [\"status\"],\n  \"time_dimensions\": [{\"dimension\": \"created_at\", \"granularity\": \"month\"}],\n  \"measures\": [\n    \"*:count\",\n    \"revenue:sum\",\n    {\"formula\": \"revenue:sum / *:count\", \"name\": \"aov\", \"label\": \"Average Order Value\"},\n    \"cumsum(revenue:sum)\",\n    \"change_pct(revenue:sum)\",\n    {\"formula\": \"last(revenue:sum)\", \"name\": \"latest_rev\"},\n    {\"formula\": \"time_shift(revenue:sum, -1, 'year')\", \"name\": \"rev_last_year\"},\n    {\"formula\": \"time_shift(revenue:sum, -2)\", \"name\": \"rev_2_periods_ago\"},\n    {\"formula\": \"lag(revenue:sum, 1)\", \"name\": \"rev_prev_row\"},\n    \"rank(revenue:sum)\",\n    {\"formula\": \"change(cumsum(revenue:sum))\", \"name\": \"cumsum_delta\"}\n  ]\n}\n```\n\nAvailable functions: `cumsum`, `time_shift`, `change`, `lag`, and more – see [docs](https://docs.motley.ai/slayer/concepts/formulas/). Formulas support arbitrary nesting — e.g., `change(cumsum(revenue:sum))` or `cumsum(revenue:sum) / *:count`.\n\n## Filters\n\nFilters use simple formula strings — no verbose JSON objects:\n\n```json\n{\n  \"source_model\": \"orders\",\n  \"measures\": [\"*:count\", \"revenue:sum\"],\n  \"filters\": [\n    \"status == 'completed'\",\n    \"amount \u003e 100\"\n  ]\n}\n```\n\nFilters support a variety of operators, composition, pattern matching. Transforms \u0026 computed columns can also be used for filtering. See [docs](https://docs.motley.ai/slayer/concepts/queries/#filters) for more.\n\n## Auto-Ingestion\n\nConnect to a database and generate models automatically. SLayer introspects the schema, detects foreign key relationships, and creates models with explicit join metadata.\n\nFor example, given tables `orders → customers → regions` (via FKs), the `orders` model will automatically include:\n\n- Joined dimensions: `customers.name`, `regions.name`, etc. (dotted syntax)\n- Count-distinct measures: `customers.*:count_distinct`, `regions.*:count_distinct`\n- Explicit joins — LEFT JOINs are constructed dynamically at query time\n\n```bash\n# Via CLI\nslayer ingest --datasource my_postgres --schema public\n\n# Via API\ncurl -X POST http://localhost:5143/ingest \\\n  -d '{\"datasource\": \"my_postgres\", \"schema_name\": \"public\"}'\n\n# Or run the same idempotent ingest pass over every configured datasource at\n# server boot — useful for YAML-drop workflows:\nslayer serve --ingest-on-startup\nslayer mcp --ingest-on-startup\n```\n\nVia MCP, agents can do this conversationally:\n\n1. `create_datasource(name=\"mydb\", type=\"postgres\", host=\"localhost\", database=\"app\", username=\"user\", password=\"pass\")`\n2. `ingest_datasource_models(datasource_name=\"mydb\", schema_name=\"public\")`\n3. `models_summary(datasource_name=\"mydb\")` → `inspect_model(model_name=\"orders\")` → `query(...)`\n\n## Datasource Setup\n\nThe fastest way is from the CLI — pass a connection URL and optionally ingest models in one step:\n\n```bash\nslayer datasources create postgresql://user:${DB_PASSWORD}@localhost/analytics --ingest\n```\n\nOr configure datasources as individual YAML files in the `datasources/` directory:\n\n```yaml\n# datasources/my_postgres.yaml\nname: my_postgres\ntype: postgres\nhost: ${DB_HOST}\nport: 5432\ndatabase: ${DB_NAME}\nusername: ${DB_USER}\npassword: ${DB_PASSWORD}\n```\n\nEnvironment variable references (`${VAR}`) are resolved at read time.\n\nSee more in the [docs](https://docs.motley.ai/slayer/configuration/datasources/).\n\n## Storage Backends\n\nSLayer ships with two storage backends:\n\n- **YAMLStorage** (default) — models and datasources as YAML files on disk. Great for version control.\n- **SQLiteStorage** — everything in a single SQLite file. Good for embedded use or when you don't want to manage files.\n\nSLayer allows easily implementing your own storage backends, which is useful for features such as tenant isolation.\n\nSee the [documentation page for storage backends](https://docs.motley.ai/slayer/configuration/storage/) for more.\n\n## Roadmap\n\n|   #   | Step                                            | Status |\n| :---: | ----------------------------------------------- | :----: |\n|   1   | Dynamic joins                                   |   ✅    |\n|   2   | Multi-stage queries                             |   ✅    |\n|   3   | Cross-model measures                            |   ✅    |\n|   4   | Aggregation at query time                       |   ✅    |\n|   5   | Smart output formatting (currency, percentages) |   ✅    |\n|   6   | Saving memories \u0026 queries                       |   ✅    |\n|   7   | Schema drift detection                          |   ✅    |\n|   8   | Unpivoting                                      |   ❌    |\n|   9   | Asof joins                                      |   ❌    |\n|   10  | Caching / pre-aggregations                      |   ❌    |\n|   11  | Access controls \u0026 governance                    |   ❌    |\n|   12  | Chart generation (eCharts)                      |   ❌    |\n\n## Examples\n\nThe `examples/` directory contains runnable examples that also serve as integration tests:\n\n| Example                            | Description                               |\n| ---------------------------------- | ----------------------------------------- |\n| [embedded](examples/embedded/)     | SQLite, no server needed                  |\n| [postgres](examples/postgres/)     | Docker Compose with Postgres + REST API   |\n| [mysql](examples/mysql/)           | Docker Compose with MySQL + REST API      |\n| [clickhouse](examples/clickhouse/) | Docker Compose with ClickHouse + REST API |\n\n## Tutorials\n\nThe `docs/examples/` directory contains Jupyter notebooks that walk through SLayer's features step by step.\n\n| Notebook                                                   | Topic                                                                                    |\n| ---------------------------------------------------------- | ---------------------------------------------------------------------------------------- |\n| [SQL vs DSL](docs/examples/02_sql_vs_dsl/)                 | How model SQL and query DSL stay cleanly separated                                       |\n| [Auto-Ingestion](docs/examples/03_auto_ingest/)            | Schema introspection, FK graph discovery, automatic model generation                     |\n| [Time Operations](docs/examples/04_time/)                  | `change`, `change_pct`, `time_shift`, `lag`, `lead`, `last` — composable time transforms |\n| [Joins](docs/examples/05_joins/)                           | Dot syntax, multi-hop dimensions, diamond join disambiguation                            |\n| [Joined Measures](docs/examples/05_joined_measures/)       | Cross-model measures with sub-query isolation                                            |\n| [Multistage Queries](docs/examples/06_multistage_queries/) | Query chaining, queries-as-models, `ModelExtension`                                      |\n\n\n## License\n\nMIT — see [LICENSE](https://github.com/MotleyAI/slayer/blob/main/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMotleyAI%2Fslayer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMotleyAI%2Fslayer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMotleyAI%2Fslayer/lists"}