search
Full-text search backed by SQLite’s FTS5 extension (or Postgres tsvector when on Postgres). Maintained automatically — every insert/update/delete to indexed entities updates the index.
Configure in your manifest at the entity level (not as a plugin entry — search is a property of the entity):
| Field | Purpose |
|---|---|
text_fields | Tokenized into the FTS5 index for keyword matching |
facets | Materialized as roaring bitmaps for instant groupBy-style counts |
sortable | Indexed so result sets paginate stably |
POST /api/search/<entity>:
facetCounts is the live count per facet value over the current filtered hit set — perfect for building Algolia-style faceted UIs without Algolia.
vector_search
Nearest-neighbor search over embeddings. Cosine similarity, in-memory index, snapshot-on-write to disk for restart durability.
Pylon doesn’t compute embeddings — pass them in from your favorite model.
- Semantic search — “posts that mean what I asked”, not just “posts containing my words”
- Related content — vector-search by an existing row’s embedding to find similar items
- Retrieval-augmented generation (RAG) — pull the top-k relevant chunks into an LLM’s context window
Scaling notes
- Search complexity is O(n × d) per query. 10k rows × 1536-dim vectors ≈ 10M float ops ≈
<10mson commodity hardware. - Above ~100k rows, switch to a dedicated vector store (
pgvector,Qdrant,Turso libsql). - Persistence is snapshot-on-write — if you have millions of writes per minute, the snapshot becomes a bottleneck. Pair with a more sophisticated index in that range.
ai_proxy
Pass-through proxy to LLM providers (OpenAI, Anthropic, Google, etc.) with token counting, rate limiting, cost tracking, and per-user budgets — all the things you’d otherwise rebuild for every AI feature.
POST /api/ai/openai/v1/chat/completions— proxies tohttps://api.openai.com/v1/chat/completionsPOST /api/ai/anthropic/v1/messages— proxies tohttps://api.anthropic.com/v1/messages- Same shape for any provider you configure
- API keys stay server-side. Browser/native clients never see your
OPENAI_API_KEY. - Per-user rate limits. Cap free tier at N requests/day; bump for paid users.
- Cost tracking per user. Every request logged with token counts.
- One set of credentials. Rotate the provider key in one place.
log_to_entity is set, every call writes a row:
mcp
Exposes your Pylon entities and functions as Model Context Protocol tools — LLM agents (Claude, ChatGPT desktop, Cursor, Continue) can call into your app.
GET /mcp/sse— Server-Sent Events stream for the MCP transportPOST /mcp/messages— JSON-RPC message endpoint
| Tool | What it does |
|---|---|
pylon_list_<entity> | List rows of an exposed entity |
pylon_get_<entity> | Fetch a row by id |
pylon_create_<entity> | Create a row (subject to policies) |
pylon_call_<fn> | Invoke an exposed function |
pylon_search_<entity> | Full-text search if the entity has search config |
https://your-app/mcp/sse with their API key as Authorization: Bearer pk_... (use an API key, not a session).
Now you can ask Claude:
“Create a todo titled ‘review PR #42’ for me, and list any other open PR-related todos.”And the model will call
pylon_create_Todo and pylon_search_Todo against your live app, scoped to whatever the API key’s owner can access.
Recommended pairings
Knowledge base / docs site:useSearch, semantic search via vector_search, LLM-powered Q&A via ai_proxy, and an MCP server for direct LLM integration.
Customer support tool: