Docs

Engram

Describe a problem; get a trained, honestly evaluated, deployed model with an HTTP endpoint and a self-contained bundle.

Get started, end to end

  1. Create an account and connect your AI. Sign up, then open Settings and connect your Claude or Codex account. Engram uses it to plan jobs, label data and write reports, so the intelligence runs on your own account.
  2. Give your coding agent access. Pick one of two ways (the table in CLI or MCP for your agent compares them):
    • CLI. Run curl -fsSL https://engramlab.cloud/install.sh | sh, then engram login (approve in the browser), then engram init inside your repository. That adds a skill telling your agent when to use Engram and which commands to run.
    • MCP. In Settings press Create install command and paste the command for your agent. Nothing to install, and no sign-in step afterwards.
  3. Describe the problem to your agent. For example: “users are spamming marketplace listings, fix it. The data is listings.csv.” The agent runs engram solve (or calls the engram_solve tool) with your file and the label column.
  4. Engram does the work. It plans the job, compares several model designs on your data, tests the winner once on data it never saw, and deploys it. Training runs on GPUs we provide, in an isolated sandbox per job, and keeps going if your laptop sleeps.
  5. Read the verdict. delivered means it cleared the bar you set, below_bar means it did not (do not act on its predictions automatically), and infeasible means the data cannot support the task. The report shows the held-out score, the baseline and the confidence interval.
  6. Use the model. Your agent wires in the HTTP endpoint (POST /api/v1/models/<id>/predict with your API key) or downloads the self-contained bundle and runs it anywhere. Later, engram drift checks that the live model still matches its test data, and engram retrain updates it from fresh labeled data.

Quickstart

curl -fsSL https://engramlab.cloud/install.sh | sh     # needs Node 18+
engram login                          # approve in the browser
engram connect claude                 # optional: plan with your Claude account
engram solve "flag listings that are spam vs legitimate" --data listings.csv --target is_spam --min-score 0.9

No data? Leave out --data and Engram sources a permissively licensed public dataset: text for text classification, or a table (target and input columns picked by your agent) for tabular tasks.

Examples

1. You have labeled data. A CSV of support tickets with an is_spam column.

engram solve "flag spam tickets" --data tickets.csv --target is_spam --min-score 0.9

Engram profiles the file, plans 2–4 designs, cross-validates them in parallel, and scores the winner once on a holdout it never trained on. You get a verdict, a report (score with a 95% interval, baseline, per-class metrics, leakage checks, latency, cost), a live endpoint and a bundle. If the score is under --min-score the verdict is below_bar and the report says why.

2. You have no data (text classification).

engram solve "classify app reviews as bug report, feature request or praise"

Your agent searches Hugging Face, keeps only permissively licensed datasets, maps their labels to yours, and records where the data came from in the model card. Thin classes are topped up with synthetic examples used for training only, never for scoring.

3. Your coding agent finds the problem. After engram init, an agent working in your repo can call engram_solve with a description and a local file, poll engram_status, then use the model:

engram predict mdl_7f3a "refund me now or I dispute the charge"
→ {"label": "complaint", "confidence": 0.94}

curl -H "Authorization: Bearer $ENGRAM_KEY" -d '{"inputs":["..."]}' https://engramlab.cloud/api/v1/models/mdl_7f3a/predict

Tabular problems such as churn or price prediction work the same way with a table: set --target and, if you like, compare more designs with --folds and --repeats.

How a job runs (classification and regression)

Image, audio, text-generation and custom tasks follow the same plan, data, evaluation and verdict steps; their specifics are in the sections below.

  1. Plan. Your connected agent (or the deterministic planner) reads the problem and a profile of your data and picks the task type, target, metric, labels and 2–4 candidate designs — or declares the problem infeasible.
  2. Data. Your labeled upload is used as is. An unlabeled upload is labeled (up to 400 sampled rows) by your agent. With no upload, Engram searches Hugging Face, keeps only permissive licenses, lets your agent choose and map labels, and records provenance.
  3. Synthetic gap-filling. For text tasks, classes below ~35% of the largest class get agent-written examples. They are added to training folds only.
  4. Parallel design search. All candidate designs train concurrently with k-fold cross-validation on the training split. Duplicates are removed before splitting.
  5. Evaluation. The CV winner is scored once on the untouched holdout, with a bootstrap 95% CI, a majority/mean baseline, per-class metrics, leakage checks and single-row latency.
  6. Verdict & bake. delivered, below_bar or infeasible. Delivered and below-bar models get a live endpoint and a zip bundle. The shipped model is the exact model that was scored.

Your AI account

Engram never uses a shared AI key for your jobs. Connect your own account; Engram runs Claude Code or the Codex app server in an isolated, per-user home on its servers. Sign-in happens on claude.ai or chatgpt.com — Engram only receives the resulting session.

engram connect claude      # opens claude.ai, then paste the code it shows
engram connect codex       # device code flow on chatgpt.com
engram whoami              # shows which accounts are connected
engram disconnect claude   # deletes the session from Engram's servers

Pick the planner per job with --provider auto|claude|codex|none. If an agent call fails, that step falls back to the deterministic path and the run log says so.

Images and audio

Zip your files one folder per class (cats/1.jpg, dogs/2.jpg), or any layout plus a labels.csv with file,label columns. Images: jpg, png, webp, bmp, gif. Audio: wav, flac, ogg, mp3 (first 10 seconds are used).

engram solve "tell apart defective and good parts" --data parts.zip
engram solve "classify bird calls by species" --data calls.zip --type audio_classification
engram solve "classify photos as cat or dog" --type image_classification      # no data: public dataset

Engram embeds every file once on a Modal GPU with a frozen pretrained encoder (CLIP for images, the Audio Spectrogram Transformer for audio), then runs the same design search, holdout evaluation and verdict as for tables, comparing logistic regression, a linear SVM-style head, nearest neighbours and a small neural head. It does not fine-tune the encoder, which is what keeps jobs cheap and fast; domains far from web photos or general audio may score lower. Duplicate files are removed by content hash before splitting.

Predict with base64-encoded file contents, at most 16 per request: {"inputs": ["<base64 jpeg>"]}. Without data, Engram searches permissively licensed Hugging Face datasets that have an image or audio column. The bundle needs torch and transformers (listed in its requirements) and downloads the encoder on first use.

Datasets

Engram builds the data as well as the model. A dataset job needs no model: describe what you need, and you get clean train, validation and test files plus a datasheet. Train on it with engram solve "…" --dataset ds_…, or download it.

engram dataset "support messages about billing problems, with the issue type" --source web --labels billing,bug,other --rows 2000
engram dataset "seed-stage companies building AI coding agents: name, site, what they do, funding" --source agent --rows 300 --effort high
engram dataset "rare fraud-like transactions described in plain text" --source synthetic --labels fraud,legit --rows 600
engram dataset "pull the price and specs from these product pages" --source urls --data urls.csv
engram dataset "photos of cracked and intact phone screens" --source hf --modality image --labels cracked,intact
engram dataset "bird songs by species" --source hf --modality audio --rows 600
engram dataset "street signs" --source web --modality image --labels stop,yield,speed-limit --gold-review 60
engram label "urgent means the customer cannot use the product" --data tickets.csv --labels urgent,normal --gold-review 100
engram datasets          engram dataset-download ds_9a1f          engram solve "route tickets" --dataset ds_9a1f

Where the rows come from (--source). The web sources run on Exa and need an Exa key configured on the server; synthetic and your own data do not.

  • hf: a public dataset from the Hugging Face Hub, for text, images or audio. Your agent writes search queries, Engram inspects the candidates, your agent picks the best one and the columns to use, and Engram downloads a sample. The dataset, its license and a link go into the datasheet. This source needs no Exa key.
  • web: passages (or images, see below) from a bulk Exa search. One search returns at most 100 results, so a crawl runs many queries (your agent writes 6 to 20 varied ones), several date windows, and repeats with saturated domains excluded to reach new ones. Each document keeps its URL, domain, publication date, the query that found it and a license class.
  • agent: structured records researched by Exa Agent. Your agent designs the columns (3 to 12 typed fields, a key field that identifies a record, evidence URLs) and Exa Agent returns schema-validated JSON, with --effort from low to ultra (ultra can run for hours). Agent returns up to about 100 records per run, so Engram runs it repeatedly, passing everything found so far as an exclusion list, until the target or the budget is reached. Records are researched with web evidence, but the schema checks shape, not facts: verify what matters.
  • webset: a large list that must meet plain-language criteria, optionally enriched with extra columns per item (Exa Websets). It needs a paid Websets plan and is billed in Websets credits, which the API does not report back, so Engram shows no dollar figure for it.
  • urls: you upload a table with a url column. For text, Exa Contents fetches clean text for every page, or extracts typed fields from each page when you describe the columns. For images and audio, the URLs point at the files themselves and Engram downloads them.
  • synthetic: your agent writes examples scenario by scenario. Every example is then labeled again, blind, by independent passes and kept only if all of them agree with the label it was written for. The datasheet records how many were generated and how many survived.
  • upload: your own table, cleaned and optionally labeled. With no source flag, Engram uses your upload if you give one, and otherwise your agent chooses.

Images and audio (--modality image|audio). A media dataset works the same way as a text one: a source, optional labels, cleaning, and a zip. Sources are Hugging Face (hf), a zip with one folder per class or a labels.csv (upload), a table of file URLs (urls), and, for images, a web search (web, which finds the images on the pages Exa returns). Downloads only fetch public addresses over http(s), refuse private and cloud-metadata addresses, check the content type and cap the file size. Every file is checked: unreadable and tiny or very short files are dropped, exact duplicates are removed by file hash, and near-identical images are removed by perceptual hash. You get train.jsonl, validation.jsonl and test.jsonl manifests, the files in a clean folder tree by split and label, a datasheet and a zip.

Labeling media. Labels from the source (folders, labels.csv, a Hugging Face label column) are kept. Unlabeled images can be labeled by CLIP zero-shot against your label list; the confidence is a softmax over your labels, not a measured accuracy, so low-confidence images go to the review queue and you can add a hand-labeled gold set. Your agent does not see the images. Audio has no automatic labeler: use a source that already has labels, or build it unlabeled. Review items show the image, or play the first three seconds of the clip. A media dataset with at least two classes can train a classifier: engram solve "…" --dataset ds_….

Licenses are a setting, not a gate. By default Engram keeps everything it finds: raw web data, whatever its license. Every document still carries a license class (Wikipedia and the Stack Exchange sites as cc_by_sa, Project Gutenberg and US government sites as public_domain, everything else unknown) and the datasheet lists the mix, so you can filter later. Set --license open (the dashboard's Web license filter) to keep only open-licensed domains. The classes are a heuristic by domain, not legal advice; what you do with the data is your call.

AI labeling (--annotation label, or engram label). Your own Claude or Codex labels the rows. Each row gets several independent passes (default 3, up to 5) with different framings and a shuffled order; if both accounts are connected the passes alternate between them, so agreement means two different models agree. Confidence is the share of passes that chose the winning label, and a tie counts as low confidence. Your agent labels up to about 1,500 rows directly; the rest are labeled by a text model trained on those, kept only where it is at least 85% sure and marked source: propagated.

Starting a gold set from the dashboard. Datasets → New dataset → Label each row → Hand-label a gold set (for example 100). When the job finishes, open the dataset, click Create a review link, send it, and press Apply decisions & rebuild once the rows are done. From the CLI: --gold-review 100, then engram review ds_….

How good are the labels? AI labels only measure agreement with the labeler unless something checks them. Engram offers three checks, and the datasheet says plainly when none was done:

  • Hand-labeled gold set (--gold-review 100, or Hand-label a gold set in the dashboard): a random sample of rows, confident or not, goes to your own people to label without seeing the AI's answer. Comparing the two gives an unbiased accuracy with a 95% interval. Use this when you need a number you can defend.
  • Gold examples you already have (--gold gold.csv): a small table with your text and the correct label. They are labeled blind with the same passes, and the report gives accuracy with a 95% interval, recall per label and accuracy by agreement level. The gold rows are then added to the dataset as human-labeled.
  • Your own labelers: on the dataset page, Create a review link gives you a secret link for people without an Engram account (teammates, domain experts, contractors). They enter a name and label rows on any device; the dataset page shows how many each person decided. You can revoke the link at any time. Gold rows are shown without the AI's answer. Engram does not supply labelers.
  • Review queue and spot checks (engram review ds_…, or the dataset page): low-confidence rows are held out of the dataset until someone on your team decides them, and a random sample of confident rows is queued as spot checks. Decide the rows, then apply: the dataset is rebuilt and the datasheet updated. The people are yours; Engram does not supply a labeling workforce.

Cleaning always runs: exact and near-duplicate removal (MinHash, 80% similarity), masking of emails, card numbers, SSNs, IBANs, IP addresses and phone numbers (or dropping those rows with --pii drop, or leaving them with --pii off), a cross-validated model that flags labels it strongly disagrees with (suspect_label), a check that train and test do not overlap, and stable splits. Masking is pattern-based and can miss unusual personal data.

Generated outputs (--annotation generate with --instruction) write an output for each input, such as a summary or an extraction, and a second pass drops outputs that are wrong, incomplete or unsupported by the input. The datasheet notes that these were not compared with human references.

You get a zip: train.jsonl, validation.jsonl, test.jsonl, dataset.csv, DATASHEET.md (contents, cleaning, label quality, provenance, license mix) and qa_report.json. Datasets are capped at 20,000 rows, and Exa spend is capped per job (--max-cost lowers it).

Exa features not used. Exa's Batch API is limited to enterprise accounts and covers searches and agent runs only, so Engram runs those itself. Monitors (scheduled searches that call a webhook) would let a dataset refresh itself; that needs a webhook receiver that appends to the dataset, and it is not built. To refresh a dataset today, run the same command again and train on the newer one.

Text generation

For tasks you can show with examples: extract a field, rewrite in a house style, summarize, turn text into structured output. Upload a table with an input column and an output column.

engram solve "pull the invoice number out of the email body" --data pairs.csv --type text_generation --text body --target invoice_number --min-score 0.9

Engram fine-tunes Flan-T5 small and base on a Modal GPU, compares them on a validation split, refits the winner on train plus validation and scores it once on an untouched test split. The metric is ROUGE-L by default (--metric exact_match for strict outputs). The verdict is relative to the better of two baselines: copying the input, and always answering with the most common training output. It needs at least 40 pairs; a few hundred is realistic. The report lists the worst test examples so you can see how it fails.

Predictions return {"text": "..."}. This built-in type uses small, cheap Flan-T5 models. For a larger fine-tuned language model (instruction following, chat style, reasoning with checkable answers), use a custom task: your agent fine-tunes an open LLM on your examples. Without data Engram can look for a permissively licensed public input/output dataset, which is only a good fit for generic tasks such as summarization.

Change a language model (model operations)

Sometimes the model already exists and you want to change it: make it fit a smaller GPU, combine two fine-tunes, teach a small model what a big one knows, or remove its refusals. Engram applies a known framework and then does the part nobody does by hand: it measures the original and the result on the same prompts with the same predictor, and gives a verdict that is allowed to say no. The result is a served model with an endpoint and a downloadable bundle, like any other.

  • quantize: bitsandbytes bnb-4bit / bnb-8bit; GGUF through llama.cpp (gguf-q4_k_m, q5_k_m, q6_k, q8_0, q3_k_m, q2_k, q4_0) for Ollama and llama.cpp; gptq-4bit and awq-4bit through llm-compressor.
  • merge: mergekit with linear, slerp, ties, dare_ties or task_arithmetic. The last three need the common base model the sources were fine-tuned from. The result is compared with every source, and says whether it beat them.
  • distill: the teacher answers your prompts and the smaller student is trained on its answers (LoRA, merged back). The result reports how much of the gap to the teacher it closed, and is infeasible if the student did not improve.
  • abliterate: removes refusal behavior. heretic (the default) runs the Heretic tool, a search over many settings that keeps the best balance of fewer refusals against drift from the original; it is slower (40 trials by default). direction is Engram's built-in classic method: it finds the one direction that separates refusing from answering and removes it from the weights in a single fast pass, with no tuning. See below.
engram ops quantize Qwen/Qwen2.5-7B-Instruct --method bnb-4bit --data prompts.csv --target output
engram ops quantize Qwen/Qwen2.5-3B-Instruct --method gguf-q4_k_m
engram ops merge owner/model-a owner/model-b --method slerp
engram ops merge owner/ft-1 owner/ft-2 --method dare_ties --base owner/base --weights 0.5,0.5
engram ops distill --teacher Qwen/Qwen2.5-7B-Instruct --student Qwen/Qwen2.5-3B-Instruct --data prompts.csv
engram ops abliterate Qwen/Qwen2.5-7B-Instruct --method heretic --params trials=40 --i-understand
engram ops "quantize Qwen/Qwen2.5-7B-Instruct to 4 bit so it fits a 12 GB GPU"

What is measured

  • Quality kept. With example prompts (--data, an input column and an output column) it is your task score after divided by before, using the metric you pick (exact_match, rouge_l, …), with a 95% interval from a paired bootstrap on the held-out set. Without prompts it is the model's likelihood of general text (perplexity), and the report says your task was not measured. --examples agent has your own Claude or Codex write the prompts.
  • Size, GPU memory, tokens per second and latency before and after, KL divergence of the next-token distribution from the original, and perplexity.
  • Verdict. Delivered when the operation did what it is for and quality kept is at least --min-retained (default 0.95 for quantize, 0.98 for merge, 0.9 for distill and abliterate). Below bar when it did what was asked but missed that. Infeasible when it did not do it (not smaller, no better than the student it started from, refusals barely changed).

Abliteration

Abliteration removes a model's refusal behavior. Real uses exist (over-refusal in medical, legal or security work, and alignment research), and it is also the operation most open to misuse, so it has its own rules. You must pass --i-understand (the dashboard asks you to tick a box; an agent may set it only when you said so). It runs only on open-weight models downloadable without a token whose license clearly allows modification (Apache-2.0, MIT, BSD, CC-BY-4.0, …); anything else is refused with the reason. Refusals are counted with a keyword rule on held-out prompts from a public harmful-behaviors set, before and after, next to the KL divergence and the quality kept: a fast heuristic that can miss polite partial refusals, so the report shows sample responses. The model card records that the model was modified and from which source models, and the report carries a notice. Heretic is licensed AGPL-3.0; Engram runs it unmodified as its own command.

Cost and time

Engram looks up the models first (size, license, whether they download without a token), picks the smallest GPU that fits (L4 up to eight H100s) and logs an estimate of time and cost before the run starts, the same estimate card as a custom task. It is a formula from the model sizes, not a promise. --max-cost refuses to start a run whose estimate is higher and caps the hard stop. Everything runs in an isolated Modal sandbox from a pre-built image (torch, transformers 5, peft, trl, bitsandbytes, mergekit, llm-compressor, Heretic, llama.cpp), so there is nothing to install. The first call to a GGUF model runs on CPU; the others need a GPU, chosen from the size.

A model on your own machine

Engram downloads models by their Hugging Face id, because the work runs in the cloud and cannot see your disk. If your model is local and can be public, push it with the Hugging Face CLI, then use its id. The repo must be public and hold safetensors files.

hf auth login
hf upload your-name/your-model ./local-model-folder
engram ops quantize your-name/your-model --method bnb-4bit

Confidential weights should not be made public, so private models are not supported yet. For those, run the same frameworks yourself (the versions are listed under the custom task environments).

Not covered: models that are not public on Hugging Face (private or gated models need a token Engram does not hold, and models on your own machine cannot be reached from the cloud sandbox; push them to Hugging Face first), models not published as safetensors, non-text models, and models beyond about 640 GB of GPU memory. These operations have been run end to end on small models; expect larger ones to take longer than the estimate says until you have seen one run.

Drift and retraining

Every prediction call updates a daily tally of predicted labels and confidence. engram drift <model> (or GET /api/v1/models/{id}/drift, or the job page) compares the last 7 days with the class mix of the test set the model was scored on. stable, watch (distance over 0.15) or drifting (over 0.3, or a label the model was never tested on). It needs 50 predictions and applies to classification models.

engram drift mdl_7f3a
engram retrain mdl_7f3a --data new_labeled.csv     # POST /api/v1/models/{id}/retrain {"upload_id": "upl_…"}

Retraining reruns the original job on the fresh data and creates a new model that records which one it replaces. The run log shows the score change; the old model keeps serving until you switch. Models that were sourced from public data retrain without a file. Drift measures the predicted label mix, not accuracy: it tells you when to look, not whether the model is wrong.

CLI

engram login | logout | whoami      engram upload <file>      engram connect claude|codex      engram init (adds the agent skill)

engram solve "<problem>" [--data file.csv|dir.zip] [--dataset ds_…] [--target col] [--text col1,col2]
             [--labels a,b,c] [--type text_classification|tabular_classification|tabular_regression|
                                      image_classification|audio_classification|text_generation|custom]
             [--metric f1_macro|accuracy|f1_weighted|rmse|mae|r2|rouge_l|exact_match|wer|box_f1]
             [--min-score 0.9] [--max-latency 50] [--max-cost 0.25] [--provider auto|claude|codex|none]
             [--folds 5] [--repeats 1] [--designs a,b] [--parallel|--sequential] [--gpu]
             [--name my-model] [--no-sourcing] [--no-synthetic] [--detach] [--json]
engram status <job> [--watch]       engram jobs        engram cancel <job>
engram models                        engram predict <model> "text" '{"col": 1}' photo.jpg   (or --file in.jsonl)
engram drift <model>                 engram retrain <model> [--data new.csv] [--detach]
engram download <model> [-o out.zip]

engram dataset "<what you need>" [--source hf|web|agent|webset|urls|synthetic|upload] [--modality text|image|audio]
               [--annotation label|generate|none] [--labels a,b,c] [--instruction "…"] [--rows 1000]
               [--data raw.csv|files.zip] [--gold gold.csv] [--gold-review 100] [--passes 3]
               [--license any|open] [--pii mask|drop|off] [--effort low|auto|high|ultra] [--max-cost 5] [--detach]
engram label "<guidelines>" --data raw.csv --labels a,b,c [--gold gold.csv] [--gold-review 100]
engram datasets          engram dataset-download <ds> [-o out.zip]
engram review <ds>                   list rows waiting for a person
engram review <ds> <item> <label>    decide one row           engram review <ds> --apply   rebuild with the decisions
engram review <ds> --share           create the review link for your own labelers      engram review <ds> --revoke

engram ops quantize <owner/model> [--method bnb-4bit|bnb-8bit|gguf-q4_k_m|gguf-q5_k_m|gguf-q6_k|gguf-q8_0|gguf-q3_k_m|gguf-q2_k|gguf-q4_0|gptq-4bit|awq-4bit]
engram ops merge <model> <model> […] [--method linear|slerp|ties|dare_ties|task_arithmetic] [--base <model>] [--weights 0.6,0.4]
engram ops distill --teacher <model> --student <model> --data prompts.csv
engram ops abliterate <owner/model> [--method heretic|direction] --i-understand [--params trials=40,kl_budget=0.5]
             heretic (default): search over many settings, slower, best balance.  direction: built-in, one fast pass.
             Heretic picks, from its results, the trial with the fewest refusals whose KL divergence stays under kl_budget (a fixed rule, no AI involved).
             common: [--data prompts.csv] [--target output] [--text input] [--metric rouge_l|exact_match|…] [--min-retained 0.95]
                     [--examples agent] [--min-refusal-drop 0.6] [--max-cost 5] [--provider auto|claude|codex|none] [--detach] [--json]
engram ops "quantize Qwen/Qwen2.5-7B-Instruct to 4 bit"      (a sentence works too; abliteration still needs --i-understand)

Supported data: CSV, TSV, JSONL, JSON, Parquet, TXT (one text per line), or a ZIP of images or audio (or of files plus a records.jsonl for custom tasks), up to 100 GB per file (see Big files). Every command takes --json where it prints a result.

Big files

Datasets, zips of images or audio, and model bundles can be many gigabytes, so they never travel through the Engram web server. Uploads go from your computer straight to storage, then are copied next to the compute; downloads come straight from storage.

engram upload listings.zip          # prints an upload id (any size up to 100 GB)
engram solve "…" --data listings.zip  # does the same upload for you
engram download <model> -o model.zip
  • One request or parts. A file up to about 5 GB is one request. A bigger file is sent in 256 MB parts, four at a time, and each part is retried on its own. The storage service checks every part and assembles the file; Engram writes no assembly code.
  • Checked end to end. The CLI computes the file's SHA-256 first. After the file reaches the compute side, Engram recomputes it and refuses the upload if even one byte differs, so a damaged dataset is never used. The size is checked too.
  • Nothing lingers. The staged copy is deleted as soon as it has been copied, and unfinished uploads are removed after a day. Downloads are prepared once, kept for a day, and served by a link that expires in an hour.
  • Without the CLI. The REST API has the same flow: POST /api/v1/uploads/sessions with the file name and size, PUT the file to the returned URL, then POST /api/v1/uploads/sessions/<id>/complete. A job that names an upload still being prepared is refused with a clear message until it is ready.

CLI or MCP for your agent

Both let a coding agent drive Engram. They are two doors into the same service, with the same jobs, models and account. Pick one; you do not need both.

CLI + skillMCP
SetupInstall it (curl … | sh), engram login, engram initPaste one command from Settings. Nothing to install
RunsOn your machineOn our server
Your filesRead from disk and sent straight to storage (engram upload), up to 100 GB, checked end to endThe agent runs one curl command from your terminal, up to 5 GB; bigger files use the CLI; small files can be pasted
Agent contextNothing until used; the agent reads --helpThe 15 tool definitions sit in context for the whole session
Works inAgents with a terminalClaude Code, Codex, Cursor, and Claude on the web or desktop

Which to use. If your agent has a terminal, the CLI is lighter on context. Use the MCP when you want nothing to install, or in Claude on the web or the desktop app.

CLI with an agent. Run engram init in a repository. It adds a skill (.claude/skills/engram/SKILL.md) that tells the agent when to reach for Engram and which commands to run, with --json for machine-readable output.

MCP. In Settings, under Connect your coding agent, press Create install command. You get one command per agent with your personal key already inside; paste it and you are done, with no sign-in step afterwards. For example, in Claude Code:

claude mcp add --scope user --transport http engram https://engramlab.cloud/mcp --header "Authorization: Bearer <your key>"

# Codex
export ENGRAM_API_KEY=<your key>
codex mcp add engram --url https://engramlab.cloud/mcp --bearer-token-env-var ENGRAM_API_KEY

# Cursor: .cursor/mcp.json
{ "mcpServers": { "engram": { "url": "https://engramlab.cloud/mcp", "headers": { "Authorization": "Bearer <your key>" } } } }

Claude on the web or the desktop app. Add https://engramlab.cloud/mcp as a custom connector. Claude opens a browser to sign you in and press Allow, with no key. Disconnect any connected app in Settings. In Claude Code you can also use this sign-in instead of a key: add the server without --header, then run /mcp and choose Engram.

Files. The MCP runs on our server and cannot read your disk. For a file, the agent calls engram_upload_url with the file's name and size (and, ideally, its SHA-256). It gets a curl command, runs it in your terminal, and calls engram_upload_done. The file goes straight to storage, never through the conversation or our servers; for files up to about 5 GB it is one command. Then the agent passes the returned id as upload_id. For bigger files the agent asks you to use the CLI (engram upload). Without a terminal, such as in the Claude app, small files go in as data_text (up to 5 MB). Downloads work the same way: engram_download and engram_dataset_download return a link to the file in storage.

Tools: engram_solve, engram_upload_url, engram_status, engram_predict, engram_models, engram_jobs, engram_download, engram_cancel, engram_drift, engram_retrain, engram_dataset, engram_datasets, engram_dataset_review, engram_dataset_download and engram_model_ops (quantize, merge, distill or abliterate an existing model; abliteration needs acknowledge: true, which an agent may set only when you said so). engram_solve covers every task type in these docs, including task_type: "custom", whose jobs log a time and cost estimate before training and can take hours, so poll engram_status. A call answers within about a minute; long jobs are polled.

REST API

Authenticate with Authorization: Bearer <key>. Create keys in Settings.

POST https://engramlab.cloud/api/v1/uploads?filename=data.csv      (raw file body)        → {"id": "upl_…"}
POST https://engramlab.cloud/api/v1/jobs
     {"task": "...", "upload_id": "upl_…" | "dataset_id": "ds_…", "target": "label", "task_type": "…", "min_score": 0.9,
      "max_cost_usd": 0.25, "folds": 5, "repeats": 1, "designs": […], "execution": "parallel"}  → job
POST https://engramlab.cloud/api/v1/jobs  {"task": "quantize …", "task_type": "model_ops", "upload_id": "upl_…" (optional prompts), "target": "output", "metric": "rouge_l",
      "ops": {"operation": "quantize|merge|distill|abliterate", "method": "bnb-4bit", "model": "owner/name", "models": […], "base_model": "…",
              "teacher": "…", "student": "…", "weights": […], "min_retained": 0.95, "examples": "agent", "acknowledge": true,
              "params": {"trials": 40}}, "max_cost_usd": 5}  → job (result.model_ops has the before/after table)
GET  https://engramlab.cloud/api/v1/jobs                                                         → your jobs
GET  https://engramlab.cloud/api/v1/jobs/{id}?after={eventId}                                    → job + new events
POST https://engramlab.cloud/api/v1/jobs/{id}/cancel
GET  https://engramlab.cloud/api/v1/models
POST https://engramlab.cloud/api/v1/models/{id}/predict  {"inputs": ["text", {"col": 1}, "<base64 file>"]} → predictions
GET  https://engramlab.cloud/api/v1/models/{id}/drift                                              → drift report
POST https://engramlab.cloud/api/v1/models/{id}/retrain  {"upload_id": "upl_…"}                    → job
POST https://engramlab.cloud/api/v1/datasets  {"task": "…", "strategy": "hf|web|agent|webset|urls|synthetic|upload", "modality": "text|image|audio",
      "annotation": "label|generate|none", "labels": […], "rows": 1000, "upload_id": …, "gold_upload_id": …, "gold_review": 100,
      "license_policy": "any|open", "pii": "mask|drop|off", "effort": "auto", "max_cost_usd": 5}  → job
GET  https://engramlab.cloud/api/v1/datasets                  GET  https://engramlab.cloud/api/v1/datasets/{id}  (+ /download)
GET  https://engramlab.cloud/api/v1/datasets/{id}/review      POST https://engramlab.cloud/api/v1/datasets/{id}/review/{item} {"label": "…"}
POST https://engramlab.cloud/api/v1/datasets/{id}/finalize    → applies review decisions and rebuilds
POST https://engramlab.cloud/api/v1/datasets/{id}/share       → {"url": "…/review/<token>"} (DELETE revokes)
POST https://engramlab.cloud/api/public/review/{token}/{item} {"label": "…", "reviewer": "Ana"}   (no account: the shared link)
GET  https://engramlab.cloud/api/v1/models/{id}/download                                          → zip

Text models accept strings or objects with the trained text column. Tabular models accept objects keyed by column; missing columns are treated as missing values.

{"model": "mdl_…", "latency_ms": 4.1,
 "predictions": [{"label": "spam", "confidence": 0.97, "scores": {"spam": 0.97, "ham": 0.03}}]}

The bundle

model.joblib        the exact pipeline that was evaluated
metadata.json       columns, classes, design, metric
engram_runtime.py   input preparation shared with training
predict.py          python predict.py '{"text": "..."}'
serve.py            stdlib HTTP server: POST /predict
Dockerfile          docker build -t my-model . && docker run -p 8080:8080 my-model
requirements.txt    pinned scikit-learn / pandas / numpy / joblib
MODEL_CARD.md       metrics, CI, designs, provenance, limitations

Anything else (custom)

If no built-in type fits (speech transcription, object detection, instruction following, reasoning with checkable answers, ranking, structured extraction, anything you can show with examples), Engram builds it as a custom task. Your own Claude or Codex account writes the training and prediction code; Engram runs it and does every honest step itself.

  1. Your examples. Optional. A table with an input column and an output column, or a zip with a records.jsonl ({"input": "audio/1.wav", "output": "hello world"} per line) next to the files it names. Outputs can be text, numbers or JSON such as boxes. With no data, your own agent writes a few hundred varied examples scenario by scenario; the report then flags that the score measures agreement with that agent, so confirm with real examples before relying on it.
  2. Split. Engram holds out a test set and keeps its outputs away from the generated code, which only ever sees train and validation.
  3. Code and estimate. Your agent writes train.py and predict.py (starting from a pretrained model when that is best), chooses a GPU and gives an honest estimate of time and cost, which appears in the run log and as an estimate card on the job page (expected time, estimated cost, the hard stop, and how long it has been running) before training starts. If you set --max-cost and the estimate is above it, the job stops there instead of spending. If the run fails, the agent reads the log and fixes the code, up to 3 attempts.
  4. Sandbox. The code runs in an isolated Modal sandbox with a GPU if requested and internet access for model downloads. It cannot see other users' data or models, and it is capped by your spend limit, not by a fixed training time.
  5. Score. Engram runs the generated predictor on the held-out inputs and scores the outputs itself with exact match, ROUGE-L, accuracy, macro-F1, word error rate, RMSE/MAE/R², or box F1, with a confidence interval and baselines (most common output, input copied through, mean, empty answer).
  6. Ship. The verdict, report, a warm endpoint and a downloadable bundle (weights, code, harness) come out the same way as for any other model.
engram solve "transcribe support calls" --data calls.zip --type custom --metric wer
engram solve "extract the line items from invoice text as JSON" --data invoices.csv --type custom --text body --target items_json

Language models. Fine-tuning an open LLM (Qwen, Mistral, Phi and the like, with LoRA or QLoRA) is a normal custom task: instruction following, a house style, structured or tool-call output, domain Q&A, reasoning with checkable final answers, or distilling an expensive prompt into a model you host. Your agent picks the model and the GPU: T4, L4, A10G, L40S, A100, H100 or H200, up to 8 cards when the model needs them, and the environment: standard, or llm, a pre-built image with torch 2.14, transformers 5, peft, trl, bitsandbytes, mergekit, llm-compressor, Heretic and llama.cpp installed at versions known to work together, so nothing is installed at start. Your agent is told to use those frameworks (TRL and PEFT for fine-tuning, bitsandbytes or llm-compressor or llama.cpp for quantizing, mergekit for merging) instead of rewriting them. Requests to remove refusals are not run as custom code: they run as the abliterate operation. Bigger GPUs cost more and the estimate in the run log says by how much before anything is spent. For free-form quality that exact match cannot measure, use rouge_l against reference answers and read the worst failures in the report.

Predict with POST /api/v1/models/{id}/predict, at most 16 inputs per call; file inputs are sent as base64. The first call starts the model's sandbox and can take a minute for large models; later calls are fast while it stays warm. Quality depends on what your agent builds in the time limit: the score on the held-out test set is the honest measure, and the report shows the worst failures.

Usage and billing

Running jobs needs a Pro plan. It includes a monthly credit, and you can go beyond it up to a spending limit you set. The intelligence runs on your own Claude or Codex account and is not part of this.

  • What you pay for. Compute (training, evaluation, model operations and the GPU time they use), web search and fetching when Engram sources data, the storage of the models, datasets and uploads you keep, and moving big files in and out. One credit covers all four.
  • Credit and spending limit. Your monthly credit is used first. Past it, usage is added to your next invoice, never more than your spending limit. The limit is $0 by default, which means jobs stop being accepted once the included credit is used. Change it on the Billing page.
  • Before a job runs. Engram compares the job's estimate with your remaining credit and limit, and refuses to start it with a clear message if it would not fit. --max-cost lets you refuse anything above a ceiling you choose.
  • When you see the final cost. While a job runs, its estimate is held against your credit. The actual cost is settled about ten minutes after the job ends, and then appears on the Billing page. Failed and cancelled jobs are charged for the compute they actually used.
  • Where to look. The Billing page shows your plan, the credit used this period split by compute, web, storage and file transfer, your recent jobs, and everything you have stored. engram whoami shows the same totals in the terminal.
  • Stored files. Models, datasets and uploads you keep count toward storage until you delete them. Delete what you no longer need from the Storage list on the Billing page.

Limits

  • An honest score needs correct outputs you did not generate from the model itself. When your agent writes the examples, the score only measures agreement with that agent, and the report says so.
  • Custom training has no fixed time cap. A sandbox lives at most 23 hours; set --max-cost to bound spend.
  • Only the built-in types can be sourced from public datasets; custom tasks use your data or agent-written examples. To make that data first, build a dataset.
  • Training on datasets without a permissive license is refused.
  • Model operations need a text language model that downloads without a Hugging Face token. Abliteration is limited to models under a license that allows modification, and needs your acknowledgement. Quality can only be measured on the prompts and general text used; it does not cover every behavior of a model.