Agent reference
Everything a person does here — describe, upload, train, evaluate, export — is designed to be done by an AI agent too: discoverable, typed, idempotent, and bounded by a budget a human sets.
The API, MCP server and CLI are planned, not live
Machine-readable, live today: SKILL.mdllms.txtCapability manifestOpenAPI draft
01Where things stand
Where things stand
Web app
Live previewCreate, train (simulated), test and export in the browser.
OpenAgent skill
LiveOne pasted line sets it up. Your agent helps you shape the task and prepare examples, then hands off to the web app.
Read SKILL.mdREST API
PlannedDraft OpenAPI 3.1 spec, generated from the same schemas the web app uses.
Draft specMCP server
PlannedNine tools over streamable HTTP, each with a JSON Schema and a declared side effect.
ToolsCLI
Plannedtmc mirrors every tool for scripts, CI and terminal-based agents.
Commands
02The safe loop
The safe loop
Six calls take an agent from an idea to an exported model — and every step that can cost money is explicit, capped and repeatable.
01Discover
Learn what's possible and which interfaces are live.
agent →tools/list
← tmc9 tools · output kinds: single_label, multi_label, extraction · auth: bearer (scoped)
02Estimate
Free dry run before committing any money.
agent →estimate_cost({ output_kind: "single_label", label_count: 6, row_count: 2400, requirements: { min_accuracy: 0.9, max_spend_usd: 25 } })
← tmc$1.19–$2.01 · 13–23 min · 4 candidates · within_cap: true
03Register data
Data-quality issues surface before training starts.
agent →create_dataset({ name: "tickets", format: "csv", source_url: "https://…/tickets.csv?sig=…" })
← tmcds_8f2k1q · 2,400 rows · 6 labels · 0 errors · 1 note (14 duplicates removed)
04Create the job
Idempotency key and a hard spending cap are mandatory.
agent →create_model_job({ …, dataset_id: "ds_8f2k1q", requirements: { max_spend_usd: 25 }, idempotency_key: "router-2026-10-17-a" })
← tmc202 Accepted · job_7hq2m4 · queued · Retry-After: 10
05Poll
Long-running: back off as Retry-After asks, or use webhooks.
agent →get_job({ job_id: "job_7hq2m4" })
← tmcrunning · train · 62% · $1.12 of $25.00 spent · eta 9 min
06Check the bar
Evaluation on held-out data, against the requirements set.
agent →get_model({ model_id: "mdl_x91" })
← tmcsucceeded · accuracy 92.1% (≥ 90% ✓) · p95 13 ms (≤ 50 ms ✓) · spent $1.61
07Export
Signed, short-lived download with a checksum to verify.
agent →export_model({ model_id: "mdl_x91", format: "onnx" })
← tmcsupport-ticket-router-v3.onnx · 155 MB · sha256 9c1e… · expires in 15 min
03MCP tools
MCP tools
Each tool declares its side effect and the scopes it needs. Input schemas are generated from the same contract as the web app.
describe_capabilities
Read-onlyWhat this service can build, the supported output kinds, export formats, limits and current status of each interface.
GET /v1/capabilities · tmc capabilities
estimate_cost
Read-onlymodels:readFree dry run. Returns a cost range, wall-clock time and whether it fits under the cap. Call this before create_model_job.
POST /v1/estimates · tmc estimate --task … --rows 2400 --min-accuracy 0.9
create_dataset
Writesdatasets:writeRegister training examples from inline rows or an HTTPS URL. Optionally clean each input (HTML, quoted replies, signatures, repeated lines) and combine labels; models trained on them clean and combine live calls the same way. Returns data-quality issues before anything is trained.
POST /v1/datasets · tmc datasets create ./tickets.csv --text-column message --label-column team
create_model_job
Can spendjobs:createStart a long-running training job. Requires an idempotency key and a spending cap; returns immediately with a queued job.
POST /v1/jobs · tmc models create --task … --data ./tickets.csv --max-spend 25 --idempotency-key …
get_job
Read-onlymodels:readPoll a job. Honour the Retry-After hint; terminal states are succeeded, failed and canceled.
GET /v1/jobs/{job_id} · tmc jobs watch job_…
cancel_job
Writesjobs:cancelStop a running job. Nothing more is charged. Canceling a finished job returns 409.
POST /v1/jobs/{job_id}/cancel · tmc jobs cancel job_…
get_model
Read-onlymodels:readMetrics on held-out data, requirement checks, per-label scores, confusion matrix and baseline comparison.
GET /v1/models/{model_id} · tmc models show mdl_…
predict
Can spendmodels:predictRun the model on one input. Hosted models bill per call at the price in the model's metrics.
POST /v1/models/{model_id}/predict · tmc predict mdl_… "Where is my package?"
export_model
Writesmodels:exportGet a short-lived signed download for an artifact, with its SHA-256 and model card.
POST /v1/models/{model_id}/exports · tmc models export mdl_… --format onnx --out ./model.onnx
{ "mcpServers": { "the-model-company": { "url": "https://mcp.tmc.example/v1", "headers": { "Authorization": "Bearer ${TMC_API_KEY}" } } }}04REST & OpenAPI
REST & OpenAPI
The same operations over HTTPS, described by an OpenAPI 3.1 document you can feed to code generators or tool-use frameworks.
| Endpoint | Does |
|---|---|
| GET /v1/capabilities | Describe capabilities |
| POST /v1/estimates | Estimate cost |
| POST /v1/datasets | Create dataset |
| POST /v1/jobs | Create model job |
| GET /v1/jobs/{job_id} | Get job |
| POST /v1/jobs/{job_id}/cancel | Cancel job |
| GET /v1/models/{model_id} | Get model & evaluation |
| POST /v1/models/{model_id}/predict | Predict |
| POST /v1/models/{model_id}/exports | Export model |
POST /v1/jobs HTTP/1.1Host: api.tmc.exampleAuthorization: Bearer $TMC_API_KEYIdempotency-Key: router-2026-10-17-aContent-Type: application/json{ "name": "Support ticket router", "task": { … }, "dataset_id": "ds_8f2k1q", "requirements": { "min_accuracy": 0.9, "max_spend_usd": 25, … }, "mode": "training" }HTTP/1.1 202 AcceptedLocation: /v1/jobs/job_7hq2m4Retry-After: 10{ "id": "job_7hq2m4", "status": "queued", "progress": 0, "cost": { "cap_usd": 25, "estimated_usd": 2.01, "spent_usd": 0 } }05CLI
CLI
For terminal-native agents, CI pipelines and people who like scripts. Every command maps onto one tool.
$ tmc models create \ --task "Route support tickets to the right team" \ --data ./tickets.csv --label-column team \ --min-accuracy 0.90 --max-latency 50 --max-spend 25 \ --idempotency-key router-2026-10-17-a→ job_7hq2m4 queued · estimate $1.61–$2.71 · cap $25.00$ tmc jobs watch job_7hq2m4→ training 4 candidates · 62% · $1.12 spent→ succeeded · accuracy 92.1% (target 90%) · p95 13 ms$ tmc models export mdl_x91 --format onnx --out ./router.onnx06Long-running jobs
Long-running jobs
Training takes minutes, not milliseconds. Creating a job returns immediately; progress is polled or pushed.
GET /v1/jobs/job_7hq2m4 HTTP/1.1HTTP/1.1 200 OKRetry-After: 10{ "status": "running", "current_stage": "train", "progress": 0.62, "eta_seconds": 540, "cost": { "spent_usd": 1.12, "cap_usd": 25 } }POST https://your-agent.example/hooks/tmcTMC-Signature: t=1792234412,v1=5f2c…{ "type": "job.succeeded", "job_id": "job_7hq2m4", "model_id": "mdl_x91", "metrics": { "accuracy": 0.921, "latency_ms_p95": 13 } }The web app's job page is a live example: it polls the same Job resource an agent would. Watch one.
07Keys, limits & idempotency
Keys, limits & idempotency
Agents act on someone's behalf. The guardrails are part of the protocol, not an afterthought.
Scoped keys
Keys carry only the scopes an agent needs. Creating jobs and exporting weights are separate permissions.
Hard spending caps
Every job requires max_spend_usd. Keys add a monthly ceiling; jobs above the auto-approve limit wait for a human.
Idempotent creation
Retrying with the same key returns the original job — a flaky network can never buy two training runs.
| Scope | Allows |
|---|---|
| models:read | Read models, jobs, estimates and evaluations |
| datasets:write | Register training data |
| jobs:create | Start training jobs (spends money, within caps) |
| jobs:cancel | Cancel running jobs |
| models:predict | Run predictions (hosted models bill per call) |
| models:export | Download weights and containers |
# Same key + same body → the original job, never a second chargePOST /v1/jobs Idempotency-Key: router-2026-10-17-a → 202 job_7hq2m4POST /v1/jobs Idempotency-Key: router-2026-10-17-a → 202 job_7hq2m4 (replayed)# Same key + different body → rejected, nothing createdPOST /v1/jobs Idempotency-Key: router-2026-10-17-a → 409 idempotency_conflict{ "error": { "code": "approval_required", "message": "Estimated cost $38.40 exceeds this key's auto-approve limit of $25.00.", "details": { "estimate_usd": { "low": 30.70, "high": 38.40 }, "approval_url": "https://themodelcompany.example/approvals/apr_51k", "expires_at": "2026-10-18T09:00:00Z" } }}08Artifacts
Artifacts
Exports are short-lived signed URLs with a SHA-256 to verify and a model card describing data, metrics and limits.
POST /v1/models/mdl_x91/exports { "format": "onnx" }{ "artifact": { "format": "onnx", "filename": "support-ticket-router-v3.onnx", "size_mb": 155, "sha256": "9c1e…" }, "download_url": "https://downloads.tmc.example/…?sig=…", "expires_at": "2026-10-17T10:15:00Z" }Prefer to click?
The same flow runs in the browser today, with a free simulated job.