# Antigravity (/agents/antigravity) Open the MCP manager (`/mcp`) and add the server, or edit the configuration. Antigravity takes `serverUrl` for remote servers: ```json title="~/.gemini/config/mcp_config.json (or .agents/mcp_config.json in a workspace)" { "mcpServers": { "typestrict": { "serverUrl": "https://api.typestrict.ai/mcp" } } } ``` Antigravity asks you to sign in to typestrict the first time. With an API key, add `"headers": { "Authorization": "Bearer ts_..." }`. The local server (after `curl -fsSL https://typestrict.ai/install.sh | sh` and `typestrict login`): ```json { "mcpServers": { "typestrict": { "command": "typestrict", "args": ["mcp"] } } } ``` **Skills.** Antigravity reads skills from `.agents/skills` in the workspace and from `~/.gemini/config/skills`: ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ ``` Still on Gemini CLI (Gemini Code Assist Standard or Enterprise)? Use the local server the same way, under `mcpServers` in `~/.gemini/settings.json`. # ChatGPT (/agents/chatgpt) 1. Open [chatgpt.com/plugins](https://chatgpt.com/plugins), choose **+** and **Add custom MCP server**. 2. Name it typestrict, use the URL `https://api.typestrict.ai/mcp` and OAuth, and create it as a plugin. 3. Sign in to typestrict and allow ChatGPT. That is all: ChatGPT now sees every training of your account. Custom MCP servers are available on ChatGPT Business, Enterprise and Edu, on the web. ChatGPT only connects with OAuth (no API keys). Then ask: "Train a model on this spreadsheet that decides which team handles a ticket." ChatGPT sends text files (CSV, JSON, text) by their contents; for Excel, PDF, zip or large files, upload them in the [dashboard](https://typestrict.ai/trainings/new) and ask ChatGPT to take the training from there. **Skills.** Add the guidance of [typestrict-lab/skills](https://github.com/typestrict-lab/skills) to the project or GPT instructions, or give it the docs link (`https://docs.typestrict.ai/llms-full.txt`). # Claude (/agents/claude) ## Claude.ai and Claude Desktop [#claudeai-and-claude-desktop] 1. In **Customize → Connectors**, choose **Add custom connector**. On Team and Enterprise plans, an owner adds it in **Organization settings → Connectors**. 2. Name it typestrict and use the URL `https://api.typestrict.ai/mcp`. 3. Sign in to typestrict and allow Claude. The same connector works on Claude Desktop and on mobile. Claude sends text files (CSV, JSON, text) by their contents; for Excel, PDF, zip or large files, upload them in the [dashboard](https://typestrict.ai/trainings/new) and ask Claude to take the training from there. **Skills.** Zip a folder of [typestrict-lab/skills](https://github.com/typestrict-lab/skills) (the zip holds `typestrict-train/SKILL.md`) and upload it in **Customize → Skills**. ## Claude Code [#claude-code] ```bash claude mcp add --transport http typestrict https://api.typestrict.ai/mcp ``` Then run `/mcp` in Claude Code and sign in to typestrict. With an API key instead of OAuth: ```bash claude mcp add --transport http typestrict https://api.typestrict.ai/mcp --header "Authorization: Bearer $TYPESTRICT_API_KEY" ``` To send local files of any kind and save the model into your project, use the local server instead: ```bash curl -fsSL https://typestrict.ai/install.sh | sh && typestrict login claude mcp add typestrict -- typestrict mcp ``` Add `--scope project` to share the server with your team in `.mcp.json`. Skills: ```bash git clone https://github.com/typestrict-lab/skills.git && cp -r skills/typestrict-* ~/.claude/skills/ ``` Then ask: "Train a model on `data/tickets.csv` that decides which team handles a ticket, and integrate it in `src/router.ts`." # OpenAI Codex (/agents/codex) ```bash codex mcp add typestrict --url https://api.typestrict.ai/mcp codex mcp login typestrict ``` The CLI, the IDE extension and the Codex app share the configuration. With an API key instead of OAuth: ```toml title="~/.codex/config.toml" [mcp_servers.typestrict] url = "https://api.typestrict.ai/mcp" bearer_token_env_var = "TYPESTRICT_API_KEY" ``` To send local files of any kind, use the local server (after `curl -fsSL https://typestrict.ai/install.sh | sh` and `typestrict login`): ```bash codex mcp add typestrict -- typestrict mcp ``` **Skills.** Codex reads skills from `.agents/skills` in your repository and from `~/.agents/skills`: ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ ``` Codex's sandbox blocks the network by default: allow it for the session, or approve the calls to `api.typestrict.ai` when Codex asks. # GitHub Copilot (/agents/copilot) ## VS Code [#vs-code] Run **MCP: Add Server** from the Command Palette, choose HTTP and use `https://api.typestrict.ai/mcp`, or: ```bash code --add-mcp '{"name":"typestrict","type":"http","url":"https://api.typestrict.ai/mcp"}' ``` VS Code asks you to sign in to typestrict the first time Copilot uses it. The local server: ```bash code --add-mcp '{"name":"typestrict","type":"stdio","command":"typestrict","args":["mcp"]}' ``` ## Copilot CLI [#copilot-cli] ```bash copilot mcp add --transport http typestrict https://api.typestrict.ai/mcp ``` Sign in with `/mcp auth typestrict`, or add `--header "Authorization: Bearer $TYPESTRICT_API_KEY"`. The local server: `copilot mcp add typestrict -- typestrict mcp`. ## Skills [#skills] Copilot reads skills from `.github/skills` or `.agents/skills` in the repository, and from `~/.copilot/skills`: ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ ``` # Cursor (/agents/cursor) ```json title=".cursor/mcp.json (or ~/.cursor/mcp.json for every project)" { "mcpServers": { "typestrict": { "url": "https://api.typestrict.ai/mcp" } } } ``` Cursor asks you to sign in to typestrict the first time it uses the server. Use OAuth here: Cursor may skip a configured `Authorization` header when the server offers sign-in. To send local files of any kind, use the local server (after `curl -fsSL https://typestrict.ai/install.sh | sh` and `typestrict login`): ```json title=".cursor/mcp.json" { "mcpServers": { "typestrict": { "type": "stdio", "command": "typestrict", "args": ["mcp"] } } } ``` **Skills.** Cursor reads skills from `.agents/skills` and `.cursor/skills` (and the same folders in your home): ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ ``` # Devin Desktop (/agents/devin) ## Devin Desktop [#devin-desktop] Open the MCP settings and add a server, or edit `mcp_config.json`: ```json title="mcp_config.json" { "mcpServers": { "typestrict": { "serverUrl": "https://api.typestrict.ai/mcp" } } } ``` Devin asks you to sign in to typestrict the first time. The local server, after installing the [CLI](/cli): `"typestrict": { "command": "typestrict", "args": ["mcp"] }`. ## Devin CLI [#devin-cli] ```bash devin mcp add typestrict https://api.typestrict.ai/mcp devin mcp login typestrict ``` The local server: `devin mcp add typestrict -- typestrict mcp`. ## Skills [#skills] Devin reads skills from `.devin/skills` in the repository: ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .devin/skills && cp -r skills/typestrict-* .devin/skills/ ``` # AI assistants (/agents) An assistant can run the whole flow for you: send the data, answer the review, start the training, follow it to the result and wire the model into your code. Every training says what it needs next (`next_action`, see [Trainings](/trainings)), so the assistant always knows the next step. ## Remote MCP server [#remote-mcp-server] ```txt https://api.typestrict.ai/mcp ``` Nothing to install: add the URL to your assistant and sign in to typestrict when it asks (OAuth). Assistants that take custom headers can use an API key instead (`Authorization: Bearer ts_...`, from [Settings](https://typestrict.ai/settings#api-keys)). It has a tool for every step; starting a training always takes a quote and your confirmation, so no credit is spent without asking. The remote server cannot read your disk: the assistant sends text files (CSV, JSON, text) by their contents. For large files, Excel, PDF or zip, upload them in the [dashboard](https://typestrict.ai/trainings/new) and let the assistant take the training from there, or use the local server. ## Local MCP server [#local-mcp-server] The [typestrict CLI](/cli) includes the same server over stdio, `typestrict mcp`. It runs on your machine with your API key, so the assistant can send any local file and save the model into your project. ```bash curl -fsSL https://typestrict.ai/install.sh | sh typestrict login # an API key from https://typestrict.ai/settings#api-keys ``` | Assistant | Remote (`https://api.typestrict.ai/mcp`) | Local (`typestrict mcp`) | | ---------------------------------- | ---------------------------------------- | ------------------------ | | [ChatGPT](/agents/chatgpt) | Yes, OAuth | No | | [Claude](/agents/claude) | Claude.ai, Desktop and Claude Code | Claude Code | | [Cursor](/agents/cursor) | Yes | Yes | | [OpenAI Codex](/agents/codex) | Yes | Yes | | [GitHub Copilot](/agents/copilot) | VS Code and Copilot CLI | Yes | | [Antigravity](/agents/antigravity) | Yes | Yes | | [Devin Desktop](/agents/devin) | Yes | Yes | | [Others](/agents/others) | Zed, Kiro, opencode, Cline | Yes | ## Skills [#skills] [typestrict-lab/skills](https://github.com/typestrict-lab/skills) puts your assistant to work on what makes a model good: it checks and prepares the data, reviews the agent's proposal and fixes it before training, and integrates the result. They use the MCP server (remote or local) and the CLI, and carry the [tips for the best model](/best-results). ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ # Codex, Cursor, Copilot, Antigravity, opencode mkdir -p .claude/skills && cp -r skills/typestrict-* .claude/skills/ # Claude Code ``` Each assistant's page says where it reads skills. ## Without MCP [#without-mcp] Any assistant with a terminal can also run the CLI directly (`typestrict status --json`, `typestrict run`...). Add this to its instruction file (`AGENTS.md`, `CLAUDE.md`...): ```md title="typestrict instructions" ## typestrict - typestrict trains small decision models on our data. Use the typestrict CLI (install: curl -fsSL https://typestrict.ai/install.sh | sh). - Docs for assistants: https://docs.typestrict.ai/llms-full.txt. Read it before the first command. - Drive each training by its `next_action` (`typestrict status --json`). - Starting a training costs a credit: show the cost and ask before `typestrict run`. - Never print the API key or commit it. ``` # Other assistants (/agents/others) Any MCP client works with the remote server, `https://api.typestrict.ai/mcp` (streamable HTTP, OAuth or an API key in `Authorization: Bearer ts_...`), or with the local one, the command `typestrict mcp` over stdio. ```json title="Zed (settings.json)" { "context_servers": { "typestrict": { "url": "https://api.typestrict.ai/mcp" } } } ``` ```json title="Kiro (.kiro/settings/mcp.json)" { "mcpServers": { "typestrict": { "url": "https://api.typestrict.ai/mcp" } } } ``` ```json title="opencode (opencode.json)" { "mcp": { "typestrict": { "type": "remote", "url": "https://api.typestrict.ai/mcp" } } } ``` Sign in with `opencode mcp auth typestrict`. ```json title="Cline (MCP settings)" { "mcpServers": { "typestrict": { "type": "streamableHttp", "url": "https://api.typestrict.ai/mcp" } } } ``` **Skills.** Most assistants read the open skills format from `.agents/skills`; see [typestrict-lab/skills](https://github.com/typestrict-lab/skills). **For client developers.** The server publishes its metadata at `https://api.typestrict.ai/.well-known/oauth-protected-resource/mcp` (RFC 9728) and answers a request without a token with a 401 pointing at it. The authorization server is `https://typestrict.ai`: PKCE (S256), the `resource` parameter (RFC 8707), Client ID Metadata Documents or dynamic client registration, and the `iss` parameter on the redirect (RFC 9207). # Get the balance (/api/credits/get-the-balance) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List the credit history (/api/credits/list-the-credit-history) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Confirm an upload (/api/datasets/confirm-an-upload) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Copy a dataset (/api/datasets/copy-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Create a dataset (/api/datasets/create-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Delete a dataset (/api/datasets/delete-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a dataset (/api/datasets/get-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get the next example to label (/api/datasets/get-the-next-example-to-label) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Label an example (/api/datasets/label-an-example) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List a dataset's sources (/api/datasets/list-a-datasets-sources) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List datasets (/api/datasets/list-datasets) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Structure a dataset (/api/datasets/structure-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Suggest decisions (/api/datasets/suggest-decisions) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Update a dataset (/api/datasets/update-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Health (/api/health/health) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Download a model (/api/models/download-a-model) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a model (/api/models/get-a-model) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a model's package (/api/models/get-a-models-package) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get the audit of a verdict (/api/models/get-the-audit-of-a-verdict) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List base models (/api/models/list-base-models) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List models (/api/models/list-models) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Replicate a recipe (/api/models/replicate-a-recipe) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Start a training (/api/models/start-a-training) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a published model (/api/public/get-a-published-model) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a GitHub repository (/api/sources/get-a-github-repository) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a Hugging Face dataset (/api/sources/get-a-hugging-face-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Search Hugging Face datasets (/api/sources/search-hugging-face-datasets) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List trainings (/api/trainings/list-trainings) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Authentication (/authentication) Send the key as a bearer token: ```http Authorization: Bearer ts_... ``` A key acts as the account that created it: it sees and spends what that account sees and spends. Create and delete keys in [Settings → API keys](https://typestrict.ai/settings#api-keys); deleting a key stops it at once. ## AI assistants [#ai-assistants] Assistants connected to the [remote MCP server](/agents) sign in with OAuth instead: you sign in to typestrict once and allow the assistant, and it gets a token that acts as your account. To disconnect one, remove the connector in the assistant. ## Keep it secret [#keep-it-secret] * Read it from an environment variable or a secret manager, never from code or a repository. * Call the API from your servers. A key in a browser or a mobile app is a key anyone can copy. * One key per place that uses it, so revoking one does not stop the others. Keys start with `ts_`, so secret scanners can recognize a leaked one. ## Errors [#errors] A missing, unknown, disabled or expired key answers `401`: ```json { "error": "unauthorized", "message": "unauthorized" } ``` Every error has the same shape: a stable `error` code to branch on and a `message` for people. # Base models (/base-models) Your model is not trained from zero: it starts from a **base model**, an encoder that already reads language and makes typed decisions, and learns your decision on top of it. Every base model is ours, named `TS-{base}-{size}`, open and cleared for commercial use (Apache-2.0). `GET /v1/encoders` lists them with what can be picked right now. | Base model | `encoder` | Size | Languages | Context | Decision Index 0.3 | Training | | ---------------------------------------------------------------------------------- | ----------------- | ---- | --------- | ------------ | ------------------ | --------- | | [TS-moBERTo-150M](https://huggingface.co/typestrict/TS-moBERTo-150M) (recommended) | `ts-moberto-150m` | 150M | EN, PT | 8,192 tokens | 31.20 / 33.89 | Available | | [TS-Ettin-150M](https://huggingface.co/typestrict/TS-Ettin-150M) | `ts-ettin-150m` | 150M | EN | 8,192 tokens | 31.96 / 34.78 | Available | | [TS-Ettin-68M](https://huggingface.co/typestrict/TS-Ettin-68M) | `ts-ettin-68m` | 68M | EN | 8,192 tokens | 27.61 / 30.46 | Available | | [TS-Ettin-32M](https://huggingface.co/typestrict/TS-Ettin-32M) | `ts-ettin-32m` | 32M | EN | 8,192 tokens | 19.70 / 22.45 | Available | | [TS-Ettin-17M](https://huggingface.co/typestrict/TS-Ettin-17M) | `ts-ettin-17m` | 17M | EN | 8,192 tokens | 15.76 / 18.52 | Available | The [Decision Index](https://github.com/apolinario/decision-index) 0.3 public index, in our lab's run: the encoder alone, then with the code and calculator experts that ship with the published models. Measured on public benchmarks, not on your task: your own model is measured on your examples, against Jev ([the refund calculation](/refund)). The context is how much text one example can hold; longer examples are refused, never cut. ## TS-moBERTo-150M [#ts-moberto-150m] Our default base, in English and Portuguese, built for typed decisions (`choice`, `noul`, `score`, with probabilities and a confidence) on a CPU. It starts from [moBERTo](https://huggingface.co/Tropic-AI/moBERTo-orig-tokenizer) (Apache-2.0) and was published before as [Dinah-1](https://huggingface.co/Lukitaduarte/dinah-1), whose official Decision Index run scored **34.32**, with the raw results published for auditing. Held-out typed decisions (1,000 items each): 0.790 accuracy in English, 0.780 in Portuguese. ## TS-Ettin [#ts-ettin] The same recipe on the [Ettin rerankers](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1) (Apache-2.0), in four sizes, English only. The 150M one is the strongest base on the index; the smaller ones trade points for speed and memory, for phones, browsers and high volumes. Their confidence is not calibrated yet; your trained model is still measured the same way. ## What they were trained on [#what-they-were-trained-on] All five follow the same recipe on the same data, in two stages (2,048 tokens, then 8,192) and an average of both. Each source with the license its own card declares. Sources under CC BY-SA and CDLA-Sharing are used for training only and are not redistributed. | Area | Sources | | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Typed decisions | ZefanCai/Open-Jev (CC0-1.0), LocalLLaMA/typed-decisions (Apache-2.0), typed-decisions-pt translated with Qwen3-4B (Apache-2.0), tasksource/procedural-typed-decisions (Apache-2.0) | | Intents and customer support | AmazonScience/massive (CC BY 4.0), Bitext customer support (CDLA-Sharing-1.0), BANKING77 (CC BY 4.0), CLINC150 (CC BY 3.0), FAQ_BACEN (Apache-2.0) | | Inference and fact checking | WANLI (CC BY 4.0), SNLI (CC BY-SA 4.0), HoVer (CC BY-SA 4.0), FEVER-NLI (MIT; FEVER and Wikipedia CC BY-SA 3.0), ContractNLI (CC BY 4.0), bAbI-NLI (BSD), FaQuAD-NLI (CC BY 4.0), ExtraGLUE RTE and COPA in Portuguese (MIT) | | Reasoning and knowledge | CommonsenseQA (MIT), Cosmos QA (CC BY 4.0), BoolQ (CC BY-SA 3.0), HellaSwag (MIT), WinoGrande (Apache-2.0), ARC train split (CC BY-SA 4.0), QASC (CC BY 4.0), StrategyQA (MIT), BIG-bench tasks without BBH (Apache-2.0), MMLU auxiliary train, ARC and OpenBookQA parts (MIT), GSM8K (MIT), CLadder (MIT) | | Health, finance and law | PubMedQA (MIT), MedMCQA (Apache-2.0), twitter-financial-news-sentiment (MIT), financial-tweets-sentiment (MIT), NOSIBLE financial-sentiment (ODC-By), FinQA hallucination detection (MIT), pyRis/SEntFiN (MIT), CUAD (CC BY 4.0), jurisprudencias_br (CC BY 4.0), IBM Claim Stance (CC BY 3.0) | | Sentiment, emotion and moderation | GoEmotions (Apache-2.0), Civil Comments (CC0-1.0), iSarcasmEval (MIT), B2W-Reviews01 (CC BY 4.0), multilingual-sentiments in Portuguese (Apache-2.0) | | Retrieval and hallucination | ESCI (Apache-2.0), HaluEval (Apache-2.0), RAGTruth (MIT), CNN/DailyMail (Apache-2.0), SQuAD 2.0 (CC BY-SA 4.0) | | Tools | glaive-function-calling-v2 (Apache-2.0), ToolACE (Apache-2.0), hermes-function-calling-v1 (Apache-2.0), nvidia/When2Call (CC BY 4.0) | | Phishing | LLMGen-Phishing-Email-Dataset (Apache-2.0), aura-phishing-email-corpus, SpamAssassin part (CC BY 4.0) | | Chess | Lichess puzzles (CC0-1.0), google-deepmind/searchless_chess (Apache-2.0) | | Humor | newyorker_caption_contest, matching task (CC BY 4.0) | | Made by us | English to Portuguese translations with opus-mt-tc-big-en-pt (CC BY 4.0); synthetic phishing emails written with gpt-oss-120b, labels set by code (Apache-2.0); synthetic home-appliance households, RAG hallucination examples and programmatic skills (arithmetic, dates, units, sorting, graphs, code output), generated by our scripts (MIT and Apache-2.0) | The training blocks were checked against the Decision Index's public test rows (exact and near-duplicate removal, and 8-gram overlap for the newest blocks). ## Which one to pick [#which-one-to-pick] * **Not sure, or Portuguese:** TS-moBERTo-150M, the default. It is the strongest on our held-out typed decisions (0.790 in English, 0.780 in Portuguese, against 0.709 in English for TS-Ettin-150M). * **English, and you want to compare:** TS-Ettin-150M, the highest on the Decision Index. Train both on the same data and keep the version that wins on your held-out examples. * **Every millisecond or megabyte counts:** TS-Ettin-68M, 32M or 17M. Every base model trains the same way and is measured by the same rule, so trying another one is a new version of the same training. # Getting the best model (/best-results) * **Your own categories win.** The model beats Jev by far on decisions with your company's own answers (your queues, teams, products, intents): BANKING77 0.889 against 0.797 macro-F1, a customer-support set 0.998 against 0.771. On generic questions with little data (the topic of a news text, the type of a contract clause with a few hundred examples) Jev already knows a lot and the margin is thin. Frame the decision around your own answers. * **Examples per answer matter more than the total.** Aim for hundreds of labeled examples per answer when you have them. Our base models are pretrained on decisions, which helps most with very few examples; with many, your data decides. * **The weakest answer sets the bar.** A model is as good as its worst answer: one answer with few examples drags the whole model down. Merge answers that are rare and close, or collect more of them, before training. * **Answers that do not overlap, with a description.** Each answer's description is part of what the model reads. Write them so a person would never hesitate between two. * **The input of production.** Train on the text that exists when the decision is made, nothing that is only known later (a "resolved by" field when predicting the team that resolves it). * **Consistent labels.** When you label the test examples, the same case gets the same answer every time: the model is measured against those answers. ## Before sending [#before-sending] Send one clean table (CSV or JSON lines), not the raw export. Your AI assistant can do this for you with the [skills](/agents): 1. **One row per example**, with a text column holding everything the decision is made on (subject and body, or the fields a person would read) and nothing else. 2. **One spelling per answer**: `Billing`, `billing ` and `Faturamento` are one answer. Leave out empty rows. 3. **Rare answers fixed now**: merged with their closest answer, or with more examples. 4. **No leaks**: columns or text that only exist after the decision. 5. **No exact duplicates**, and no example longer than about 30,000 characters (they are refused, never cut). 6. **A precise goal**: the question, and one line per answer on when it applies. The closer it is, the better the first proposal. ## Checking the proposal [#checking-the-proposal] As soon as the proposal is ready, before labeling, go through it (the Review screen, `typestrict review`, or `structure.stats` in the API) and send what to change as feedback: 1. **Examples per answer.** Hundreds per answer is where the model gets good, and an answer needs at least 5 test examples to be measured. The test examples are 20% of your data (up to 2,000) when it comes with answers, or a random 150 you label when it does not: then an answer under about 3% of the data gets fewer than 5. Merge a rare answer with its closest one, or add examples of it. 2. **Answers that overlap.** Read the samples of each answer. If a person could swap two answers, merge them or rewrite their descriptions until the line between them is clear. When the data had no answers, low agreement between the pre-labelers points to the same problem. 3. **Labels that look wrong.** A sample whose answer does not match its text means the answer column is noisy: fix where the answer comes from. 4. **Every warning.** Each one names what to change. 5. **Duplicates and leaks.** The text must be what exists when the decision is made. 6. **The question.** Decide with your company's own answers. Large models already answer generic questions (topic, sentiment) well; your queues, teams and products are what only your data knows. ## When it does not beat Jev [#when-it-does-not-beat-jev] The comparison says why (`model.jev.superiority.reason`): a gain too small to be sure of, or one answer that trails Jev. More examples of the weak answers, or another [base model](/base-models) on the same data, are the next tries. Every version is measured on the same held-out examples, so versions compare fairly. ## In production [#in-production] Use the model's `confidence` to decide what to automate and what to send to a person. The result reports exactly this, accuracy over the 80% most confident answers: start by automating above a threshold and move it with what you see. Ask the model the question and options it was trained on, as they are in `decision_ai.json`. # CLI (/cli) One binary for macOS, Linux and Windows that does what the dashboard does. Open source: [typestrict-lab/cli](https://github.com/typestrict-lab/cli). ```bash curl -fsSL https://typestrict.ai/install.sh | sh # macOS and Linux; Windows: the zip on the latest release typestrict login # paste an API key, or set TYPESTRICT_API_KEY ``` ## The flow [#the-flow] ```bash typestrict train tickets.csv --goal "Which team handles the ticket?" --watch # upload, mask, read typestrict structure # the agent turns the data into training examples typestrict review # its proposal: the question, the answers, the warnings typestrict structure --feedback "..." # adjust it typestrict label # when asked, answer the test examples in the terminal typestrict run --watch # shows the cost and asks before spending the credit typestrict result # the verdict against Jev typestrict pull # decision_ai.json, tokenizer.json, onnx/model_8bit.onnx ``` | Command | What it does | | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | | `train [--goal] [--question] [--hf org/name:file] [--github org/name] [--no-anonymize] [--watch]` | Sends data and starts preparing a training. | | `status [] [--watch]` | Every training with its step and next action, or one of them. `--watch` follows it and exits with 1 if it failed. | | `structure [--question] [--feedback]` | Runs the structuring agent, or again with the decisions you picked or your feedback. | | `suggest ` | Asks the agent for decisions this data can teach. | | `review ` | Shows the agent's proposal. | | `label ` | Answers the test examples one by one. | | `encoders` | The base models and which can be picked. | | `credits` | Your balance. | | `run [--base ts-moberto-150m] [--yes] [--watch]` | Starts the training. Asks before spending unless `--yes`. | | `result ` | The verdict against Jev and until when the files can be downloaded. | | `pull [--dir]` | Downloads the model package. | | `mcp` | The MCP server over stdio, for assistants. | Every command takes `--json` for machine-readable output, so it fits scripts and CI. ## For assistants [#for-assistants] ```bash typestrict mcp ``` The same flow as MCP tools: `list_trainings`, `get_training`, `wait_for_change`, `create_dataset`, `structure_dataset`, `suggest_decisions`, `next_example_to_label`, `label_example`, `list_base_models`, `get_credits`, `quote_training`, `start_training`, `get_model`, `get_audit`, `download_model`. Starting a training always takes a quote and its confirmation, so an assistant never spends a credit without asking. The same tools are served remotely at `https://api.typestrict.ai/mcp`, with nothing to install. The local server is for when the assistant should send files of any kind from your disk and save the model into your project. Setup for each assistant: [AI assistants](/agents). # Run it anywhere (/deploy) The container is being built; today a model downloads as ONNX, weights and package. This page is its specification. The serving runtime is open source (Apache-2.0). Each model also ships as a container image: the model, a CPU runtime (ONNX Runtime) and an HTTP server, nothing to configure. It speaks the same decision API as Jev, so switching from Jev to your own model is changing a base URL. | Endpoint | What it does | | -------------------- | --------------------------------------------------------------------- | | `POST /v1/systemone` | Answers questions about a text, in Jev's request and response format. | | `GET /v1/models` | The model inside, by name. | | `GET /healthz` | `ok` when ready, for health checks. | | Variable | Default | What it does | | ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | `PORT` | `8080` | The port to listen on (Cloud Run and Lambda set it). | | `TYPESTRICT_TOKEN` | none | When set, every request must carry `Authorization: Bearer `. Prefer your platform's own auth (Cloud Run IAM, Lambda IAM) when you have it. | No GPU, no internet access and no calls to us: requests and data stay in your infrastructure. ## Docker [#docker] ```bash typestrict pull --container # or: docker load -i .tar (download link on the model page) docker run -p 8080:8080 typestrict/ ``` ```bash curl http://localhost:8080/v1/systemone -H "Content-Type: application/json" -d '{ "model": "ticket-router", "state": "I was charged twice. Please help.", "questions": { "team": { "type": "choice", "instructions": "Which team handles the ticket?", "criteria": { "billing": "Payments and invoices", "support": "Everything else" } } } }' # an answer looks like: # { "model": "ticket-router", "answers": { "team": { "type": "choice", "choice": "billing", "confidence": 0.97, # "probabilities": { "billing": 0.97, "support": 0.03 } } }, "usage": { "input_tokens": 41, "output_tokens": 0 } } ``` ## Google Cloud Run [#google-cloud-run] Cloud Run runs images from Artifact Registry. Copy the image there, then deploy: ```bash typestrict pull --to us-docker.pkg.dev///ticket-router gcloud run deploy ticket-router \ --image us-docker.pkg.dev///ticket-router \ --region us-central1 --cpu 1 --memory 1Gi \ --no-allow-unauthenticated ``` `--no-allow-unauthenticated` keeps it private: callers need an identity token from a service account with the `roles/run.invoker` role. Set `--min-instances 1` if the first request after a quiet period must be fast. ## AWS Lambda [#aws-lambda] The image carries the [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter), so the same image runs on Lambda unchanged. Lambda runs images from ECR in the same account and region: ```bash typestrict pull --to .dkr.ecr.us-east-1.amazonaws.com/ticket-router aws lambda create-function --function-name ticket-router \ --package-type Image \ --code ImageUri=.dkr.ecr.us-east-1.amazonaws.com/ticket-router:latest \ --role arn:aws:iam:::role/ \ --memory-size 2048 --timeout 30 aws lambda create-function-url-config --function-name ticket-router --auth-type AWS_IAM ``` On Lambda, CPU grows with memory: 2 GB is a good start. The first request after a cold start loads the model. ## Firebase [#firebase] Firebase Functions do not run your own images, so the model runs on Cloud Run (above) and Firebase reaches it: * **Hosting:** route a path straight to the Cloud Run service with a rewrite in `firebase.json`: ```json { "hosting": { "rewrites": [{ "source": "/api/decide", "run": { "serviceId": "ticket-router", "region": "us-central1" } }] } } ``` * **Functions:** call the Cloud Run service from your function with an identity token, as any other HTTP API. ## Kubernetes [#kubernetes] ```yaml apiVersion: apps/v1 kind: Deployment metadata: { name: ticket-router } spec: replicas: 2 selector: { matchLabels: { app: ticket-router } } template: metadata: { labels: { app: ticket-router } } spec: containers: - name: model image: /ticket-router ports: [{ containerPort: 8080 }] resources: { requests: { cpu: "1", memory: 1Gi }, limits: { memory: 2Gi } } readinessProbe: { httpGet: { path: /healthz, port: 8080 } } livenessProbe: { httpGet: { path: /healthz, port: 8080 }, periodSeconds: 30 } --- apiVersion: v1 kind: Service metadata: { name: ticket-router } spec: selector: { app: ticket-router } ports: [{ port: 80, targetPort: 8080 }] ``` The model holds no state, so it scales out with replicas (or a HorizontalPodAutoscaler on CPU). # Glossary (/glossary) **Accuracy.** The share of answers that are right. Simple, but it hides rare answers: a model that always answers the most common one can score high. **Anonymization (masking).** Replacing personal data in your files (names, emails, phone numbers, documents, card numbers) with markers such as `[EMAIL]`, before anything else reads them. **API key.** A secret that lets your code call the API as your account. Ours start with `ts_`. **Base model (encoder).** The model your model starts from. It already reads language; training teaches it your decision. See [Base models](/base-models). **Bootstrap.** Measuring again on many resamples of the same test examples, to see how much a result could move by chance. The [refund calculation](/refund) uses 2,000 of them. **Brier score and Brier skill.** How far the probabilities are from what happened. Brier skill turns it into a score from 0 to 1 where higher is better: a model that says 90% and is right scores more than one that says 51% and is right. **Calibration.** Whether "80% sure" is right about 80% of the time. A calibrated model's confidence can be trusted to decide what to automate. **Confidence.** How sure the model is of the answer it chose, from 0 to 1. **Context.** How much text one example can hold, in tokens (pieces of words). Depends on the base model. **Credit.** What a training costs. It comes back if the model does not beat Jev or the training fails. **Decision API.** An API that answers questions about a text with a typed result instead of free text: a `choice` among options, a `noul` (true or false, as a probability) or a `score` on a scale, each with probabilities. Jev's API, which your model's container also speaks, is one. **Encoder.** A model that reads a text and represents it, without writing text. Small, fast and cheap to run on a CPU, which is why it fits decisions. **Held-out (test) examples.** Examples set aside before training and never seen by the model, so the measure is honest. **Jev.** The market reference model for decisions, a large general model. We compare every model against it on your own examples. **Macro-F1.** The F1 (a balance of precision and recall) of each answer, averaged with every answer weighing the same. Rare answers count as much as common ones. **Multi-task model.** One model that makes several decisions on the same input. Measured per task against its base model. **ONNX.** An open file format for models. Runs on CPUs in any language through ONNX Runtime, in servers, browsers and phones. **Quantization (8-bit).** Storing the model's numbers with fewer bits. Smaller and faster, with a minimal loss. **Selective accuracy.** Accuracy over only the most confident answers (80% of them in the refund calculation): what you get when you automate those and send the rest to a person. **Structuring agent.** Our agent that reads your masked data and turns it into training examples for the decision you want. **Worst-class F1.** The F1 of the answer the model handles worst. Keeps an average from hiding an answer that collapsed. # Introduction (/) typestrict trains a small decision model on your data: it reads a ticket, a message or a document and answers with a structured, typed decision (a label, a yes or no, a score), the same answer shape as Jev, the market reference model. If your model does not beat Jev on examples it never saw during training, the credit comes back. ## How a training goes [#how-a-training-goes] Every training goes through five steps, in the dashboard, the API and the assistants alike: 1. **Data**: you send files, connect Google Drive or OneDrive, or start from a public dataset. Personal data is masked before anything else reads it. 2. **Review**: our agent organizes the data into training examples. You check the proposal and adjust it. 3. **Base model**: you pick the model to train on, cleared for commercial use, and confirm the cost. 4. **Training**: we train it and measure it against Jev. 5. **Result**: you download the model (ONNX and weights) and use it anywhere, without a GPU. ## Where to start [#where-to-start] # Limits (/limits) | Limit | Value | | ---------------------------------------------------- | -------------------------------------------------------------------------------------------------- | | Size of one file | 200 MB | | Files in one dataset | 500 | | Public sources (Hugging Face, GitHub) in one dataset | 10 | | Decisions built from one dataset | 12 | | Length of one decision's question | 500 characters | | Length of one adjustment to the agent | 1,000 characters | | Text of one example | The base model's context (see [Base models](/base-models)); longer examples are refused, never cut | | Test examples measured against Jev | 20% of the labeled examples, up to 2,000 | | Upload URL | Valid for 15 minutes | | Download and audit links | Valid for 15 minutes; ask for a new one any time while the files are kept | | Page of a list | 25 by default, up to 100 | | Cost of a training | 1 credit, given back if the model does not beat Jev or the training fails | Images are not used in this version: they show up as **Not used**, with the reason. # Quickstart (/quickstart) ## 1. Create an API key [#1-create-an-api-key] Open [Settings → API keys](https://typestrict.ai/settings#api-keys) and create a key. It starts with `ts_` and is shown only once: keep it in a secret manager or an environment variable. ```bash export TYPESTRICT_API_KEY=ts_... ``` Check it: curl TypeScript Python ```bash curl https://api.typestrict.ai/v1/credits \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" ``` ```ts const res = await fetch("https://api.typestrict.ai/v1/credits", { headers: { Authorization: `Bearer ${process.env.TYPESTRICT_API_KEY}` }, }) console.log(await res.json()) // { balance: 1, per_model: 1 } ``` ```python import os, requests res = requests.get( "https://api.typestrict.ai/v1/credits", headers={"Authorization": f"Bearer {os.environ['TYPESTRICT_API_KEY']}"}, ) print(res.json()) # {'balance': 1, 'per_model': 1} ``` ## 2. Send your data [#2-send-your-data] Describe the files and the decision you want. The answer has one upload URL per file, valid for 15 minutes. ```bash curl https://api.typestrict.ai/v1/datasets \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "support tickets", "goal": "Which team handles the ticket?", "files": [{ "filename": "tickets.csv", "content_type": "text/csv", "size": 48213 }] }' # { "id": "", "uploads": [{ "file_id": "", "filename": "tickets.csv", "url": "https://..." }] } ``` Upload each file to its URL, then confirm it: ```bash curl -X PUT --upload-file tickets.csv "" curl -X POST https://api.typestrict.ai/v1/datasets//files//complete \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" ``` ## 3. Follow the training [#3-follow-the-training] Every training says which step it is in and what it needs next: ```bash curl https://api.typestrict.ai/v1/trainings \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" # { "data": [{ "kind": "dataset", "id": "", "step": 1, "next_action": "wait", ... }], "next": null } ``` While `next_action` is `wait`, we are reading and masking the data. Then the agent structures it and the training moves on: [Trainings](/trainings) lists every next action and the call that answers it. # Refund calculation (/refund) Every model trained on one decision is measured against Jev, the market reference model, on your own examples. If it does not beat Jev, the credit comes back to your balance on its own. "Beat" is not "one metric by any margin": the refund calculation asks for a gain that holds up under resampling and no metric that collapses. ## The test examples [#the-test-examples] Before training, we set aside examples the model never sees: * **20% of your labeled examples**, drawn per answer so each answer keeps its share, **up to 2,000**. * When your data has no answers, the examples a person labeled in the review step instead. The draw is seeded by the dataset, so every version of a model is measured on the same examples. Jev answers the same examples through the same question: its answers are used only to measure, never to train. ## Four metrics [#four-metrics] Each system gets four scores on the test examples, all higher-is-better: | Metric | What it says | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------ | | `macro_f1` | How often the answer is right, with every answer weighing the same, so a rare answer counts as much as a common one. | | `brier_skill` | How good the probabilities are: `1 - mean Brier / 2`, from 0 to 1. Rewards being confident when right and unsure when wrong. | | `selective_acc_80` | Accuracy over the 80% most confident answers: what you get when you automate the confident ones and send the rest to a person. | | `worst_class_f1` | F1 of the weakest answer with 5 or more examples. No answer may collapse. | ## The rule [#the-rule] The weighted gain over Jev is ```text G = 0.5 × Δmacro_f1 + 0.3 × Δbrier_skill + 0.2 × Δselective_acc_80 ``` where `Δ` is our score minus Jev's. The model **beats Jev** only if both hold: 1. **The gain is real.** We resample the test examples 2,000 times (a paired bootstrap: the same draw for both systems) and recompute `G` each time. The 5th percentile of those 2,000 values must be above zero: `G > 0` with 95% confidence. 2. **Nothing collapses.** No metric may be worse than Jev's by more than its margin: 0.02 for the first three, 0.05 for `worst_class_f1`. Anything else is a refund, ties included. When probabilities tie for the top, both systems get the same benefit of the doubt: the answer counts as right if the right one is among the tied. The bootstrap's seed comes from the SHA-256 of the test examples' texts. Same examples, same answers, same numbers, every time. ## Verify it yourself [#verify-it-yourself] Each model has an audit file (`GET /v1/models/{id}/audit`): for every test example, the SHA-256 of its text, the right answer and the probabilities of both systems, plus the report with every number above. The verifier rebuilds the whole report with the Python standard library and fails if any number differs: ```bash curl -O https://typestrict.ai/verify_audit.py python3 verify_audit.py audit.json ``` The audit holds no text of yours, only hashes and probabilities, so it stays with the model's record even after its files expire (see [Retention](/retention)). ## When the guarantee does not apply [#when-the-guarantee-does-not-apply] * **Several decisions in one model** (a multi-task plan): each task is measured against the base model it started from, not against Jev, and there is no refund for the result. * **A training that fails** returns the credit too, whatever the kind of model. # Retention (/retention) The record of each dataset and model stays: its name, its numbers, the verdict against Jev and the [audit](/refund#verify-it-yourself) of that verdict. What can be downloaded or trained on is kept for a limited time. | What | How long | Then | | ------------------------------------------------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | Original upload | Until it is masked | Deleted right after masking. Only the masked copy is ever used. | | A model's files (ONNX, weights, package, test examples) | 30 days after the training ends | Deleted. The record and the audit stay. | | A model that did not beat Jev | At once | Its files are deleted when the verdict comes out: the credit came back, there is nothing to deliver. | | A published model | Until it is on your Hugging Face | Its files leave our storage; your repository is where it lives and is downloaded from. | | A dataset's data | 90 days after its last use | Deleted, including the copies we keep of previews and samples. Starting a training on it, or copying it to adjust, counts as a use and adds 90 days. | | An upload that never finished, or failed | 30 days | Deleted with its record. | | A closed account | 30 days after you ask | Everything is deleted. Until then you can cancel, and your API keys stop at once. | The dashboard shows the dates: **Available until** on Models and Data. The API returns them on every model (`files_expire_at`, and `files_deleted_at` once they went) and dataset (`data_expire_at`, `data_deleted_at`). ## After expiry [#after-expiry] * Downloading an expired model answers `410` with `"error": "expired"`. Its page, metrics and audit stay. * Expired data cannot start a training, be structured, labeled or copied (`410`). To train again, upload it again. * Download your model within 30 days of its training, or publish it to your Hugging Face from its page. Payment records are kept for 5 years and access logs for 6 months, as Brazilian law requires. # Security and privacy (/security) ## Your files [#your-files] * **Masking first.** Before anything else reads your data, we mask personal data: names, emails, phone numbers, documents such as CPF and CNPJ, and card numbers. The original upload is deleted as soon as the masked copy exists. * **The agent sees samples, not files.** The structuring agent (a language model reached through OpenRouter) sees the shape of your data and masked samples, never the raw files. * **Training machines are temporary.** Training runs on GPUs rented from vast.ai. They receive masked data only, and each machine is destroyed when the run ends. * **Jev only measures.** The comparison sends the masked test examples to Jev through OpenRouter. Its answers are used to measure, never to train. * **Your choice to skip masking.** If you declare that your files hold no personal data, masking is skipped, at your request and responsibility. ## Your model [#your-model] After training, the model runs where you put it: in your servers, your cloud, the browser or a phone. What you ask it never comes back to us. It is a file, not a service you depend on. ## Your account [#your-account] * Passwords are stored only as a hash; you can also sign in with a passkey, Google or Hugging Face. * API keys are stored only as a SHA-256 hash and are shown once. They start with `ts_`, so secret scanners can spot a leaked one. * AI assistants on the remote MCP server get access only after you sign in and allow them (OAuth with PKCE); their tokens are tied to that server and expire within an hour, renewed while the connection lasts. * Every call is checked against the owner: one account never reads another's datasets or models. ## How long we keep things [#how-long-we-keep-things] See [Retention](/retention). The [privacy policy](https://typestrict.ai/privacy) is the full and binding version of this page, with the list of providers that process data for us. # Trainings (/trainings) A training is a dataset being prepared (steps 1 to 3) or, once it runs, a model (steps 4 and 5). Each one carries `step` (1 to 5) and `next_action`, the same two fields the dashboard, the CLI and the assistants read, so any of them can drive the flow. ```json { "kind": "dataset", "id": "0199f0c4-…", "name": "support tickets", "status": "ready", "step": 2, "next_action": "structure" } ``` ## Next actions [#next-actions] | `next_action` | What it means | What to call | | ---------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | `upload_files` | Files still to send. | `PUT` each file to its URL, then `POST /v1/datasets/{id}/files/{file}/complete` | | `wait` | We are working on it. | Read it again in a few seconds: `GET /v1/datasets/{id}` or `GET /v1/models/{id}` | | `start_over` | The data could not be read. | Create a new dataset with the files fixed | | `structure` | The data is read and masked. | `POST /v1/datasets/{id}/structure`, or `POST /v1/datasets/{id}/suggest` to see decisions first | | `pick_decisions` | The agent suggested decisions. | `POST /v1/datasets/{id}/structure` with `{ "questions": [...] }` | | `label_examples` | The held-out examples need answers. | `GET /v1/datasets/{id}/labels/next`, then `POST /v1/datasets/{id}/labels/{task}` with `{ "label": "..." }` | | `start_training` | Ready to train. | `GET /v1/encoders`, then `POST /v1/datasets/{id}/models` with `{ "encoder": "ts-moberto-150m" }` (1 credit) | | `retry` | The training failed; the credit came back. | `POST /v1/datasets/{dataset}/models` again | | `download` | The model is ready. | `GET /v1/models/{id}/download` returns a link valid for 15 minutes, until `files_expire_at` | | `none` | The model's files went (expired, refunded or on your Hugging Face). | Nothing: the record and the audit stay ([Retention](/retention)) | | `expired` | The dataset's data expired. | Upload it again to train ([Retention](/retention)) | Starting a training without credits answers `402` with `"error": "no_credits"`. ## Pages [#pages] Lists come newest first, a page at a time: ```json { "data": [ ... ], "next": "6b3f…" } ``` Pass `limit` (1 to 100, 25 by default) and, for the following page, `cursor` with the last `next`. A page stays the same while new trainings arrive at the top. `GET /v1/models` and `GET /v1/datasets` also take `status` (`done` for finished models, `ready` for structured datasets). ```bash curl "https://api.typestrict.ai/v1/models?status=done&limit=10" \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" ``` # Antigravity (/br/agents/antigravity) Abra o gerenciador de MCP (`/mcp`) e adicione o servidor, ou edite a configuração. O Antigravity usa `serverUrl` para servidores remotos: ```json title="~/.gemini/config/mcp_config.json (ou .agents/mcp_config.json num workspace)" { "mcpServers": { "typestrict": { "serverUrl": "https://api.typestrict.ai/mcp" } } } ``` O Antigravity pede para você entrar no typestrict na primeira vez. Com uma chave de API, adicione `"headers": { "Authorization": "Bearer ts_..." }`. O servidor local (depois de `curl -fsSL https://typestrict.ai/install.sh | sh` e `typestrict login`): ```json { "mcpServers": { "typestrict": { "command": "typestrict", "args": ["mcp"] } } } ``` **Skills.** O Antigravity lê skills de `.agents/skills` no workspace e de `~/.gemini/config/skills`: ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ ``` Ainda na Gemini CLI (Gemini Code Assist Standard ou Enterprise)? Use o servidor local do mesmo jeito, em `mcpServers` no `~/.gemini/settings.json`. # ChatGPT (/br/agents/chatgpt) 1. Abra [chatgpt.com/plugins](https://chatgpt.com/plugins), escolha **+** e **Add custom MCP server**. 2. Dê o nome typestrict, use a URL `https://api.typestrict.ai/mcp` e OAuth, e crie como plugin. 3. Entre no typestrict e autorize o ChatGPT. Pronto: o ChatGPT agora vê todos os treinos da sua conta. Servidores MCP personalizados estão disponíveis no ChatGPT Business, Enterprise e Edu, na web. O ChatGPT só se conecta com OAuth (sem chaves de API). Depois peça: "Treine um modelo com esta planilha que decida qual time atende um ticket." O ChatGPT envia arquivos de texto (CSV, JSON, texto) pelo conteúdo. Para Excel, PDF, zip ou arquivos grandes, envie pelo [dashboard](https://typestrict.ai/trainings/new) e peça ao ChatGPT para conduzir o treino a partir daí. **Skills.** Adicione as orientações do [typestrict-lab/skills](https://github.com/typestrict-lab/skills) às instruções do projeto ou do GPT, ou dê a ele o link da documentação (`https://docs.typestrict.ai/llms-full.txt`). # Claude (/br/agents/claude) ## Claude.ai e Claude Desktop [#claudeai-e-claude-desktop] 1. Em **Customize → Connectors**, escolha **Add custom connector**. Nos planos Team e Enterprise, um owner adiciona em **Organization settings → Connectors**. 2. Dê o nome typestrict e use a URL `https://api.typestrict.ai/mcp`. 3. Entre no typestrict e autorize o Claude. O mesmo conector funciona no Claude Desktop e no celular. O Claude envia arquivos de texto (CSV, JSON, texto) pelo conteúdo. Para Excel, PDF, zip ou arquivos grandes, envie pelo [dashboard](https://typestrict.ai/trainings/new) e peça ao Claude para conduzir o treino a partir daí. **Skills.** Compacte em zip uma pasta do [typestrict-lab/skills](https://github.com/typestrict-lab/skills) (o zip contém `typestrict-train/SKILL.md`) e envie em **Customize → Skills**. ## Claude Code [#claude-code] ```bash claude mcp add --transport http typestrict https://api.typestrict.ai/mcp ``` Depois rode `/mcp` no Claude Code e entre no typestrict. Com uma chave de API no lugar do OAuth: ```bash claude mcp add --transport http typestrict https://api.typestrict.ai/mcp --header "Authorization: Bearer $TYPESTRICT_API_KEY" ``` Para enviar arquivos locais de qualquer tipo e salvar o modelo no seu projeto, use o servidor local: ```bash curl -fsSL https://typestrict.ai/install.sh | sh && typestrict login claude mcp add typestrict -- typestrict mcp ``` Adicione `--scope project` para compartilhar o servidor com o seu time no `.mcp.json`. Skills: ```bash git clone https://github.com/typestrict-lab/skills.git && cp -r skills/typestrict-* ~/.claude/skills/ ``` Depois peça: "Treine um modelo com o `data/tickets.csv` que decida qual time atende um ticket, e integre em `src/router.ts`." # OpenAI Codex (/br/agents/codex) ```bash codex mcp add typestrict --url https://api.typestrict.ai/mcp codex mcp login typestrict ``` A CLI, a extensão de IDE e o app do Codex compartilham a configuração. Com uma chave de API no lugar do OAuth: ```toml title="~/.codex/config.toml" [mcp_servers.typestrict] url = "https://api.typestrict.ai/mcp" bearer_token_env_var = "TYPESTRICT_API_KEY" ``` Para enviar arquivos locais de qualquer tipo, use o servidor local (depois de `curl -fsSL https://typestrict.ai/install.sh | sh` e `typestrict login`): ```bash codex mcp add typestrict -- typestrict mcp ``` **Skills.** O Codex lê skills de `.agents/skills` no seu repositório e de `~/.agents/skills`: ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ ``` O sandbox do Codex bloqueia a rede por padrão: libere para a sessão, ou aprove as chamadas para `api.typestrict.ai` quando o Codex pedir. # GitHub Copilot (/br/agents/copilot) ## VS Code [#vs-code] Rode **MCP: Add Server** na Command Palette, escolha HTTP e use `https://api.typestrict.ai/mcp`, ou: ```bash code --add-mcp '{"name":"typestrict","type":"http","url":"https://api.typestrict.ai/mcp"}' ``` O VS Code pede para você entrar no typestrict na primeira vez que o Copilot usa o servidor. O servidor local: ```bash code --add-mcp '{"name":"typestrict","type":"stdio","command":"typestrict","args":["mcp"]}' ``` ## Copilot CLI [#copilot-cli] ```bash copilot mcp add --transport http typestrict https://api.typestrict.ai/mcp ``` Entre com `/mcp auth typestrict`, ou adicione `--header "Authorization: Bearer $TYPESTRICT_API_KEY"`. O servidor local: `copilot mcp add typestrict -- typestrict mcp`. ## Skills [#skills] O Copilot lê skills de `.github/skills` ou `.agents/skills` no repositório, e de `~/.copilot/skills`: ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ ``` # Cursor (/br/agents/cursor) ```json title=".cursor/mcp.json (ou ~/.cursor/mcp.json para todos os projetos)" { "mcpServers": { "typestrict": { "url": "https://api.typestrict.ai/mcp" } } } ``` O Cursor pede para você entrar no typestrict na primeira vez que usa o servidor. Use OAuth aqui: o Cursor pode ignorar um header `Authorization` configurado quando o servidor oferece login. Para enviar arquivos locais de qualquer tipo, use o servidor local (depois de `curl -fsSL https://typestrict.ai/install.sh | sh` e `typestrict login`): ```json title=".cursor/mcp.json" { "mcpServers": { "typestrict": { "type": "stdio", "command": "typestrict", "args": ["mcp"] } } } ``` **Skills.** O Cursor lê skills de `.agents/skills` e `.cursor/skills` (e das mesmas pastas na sua home): ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ ``` # Devin Desktop (/br/agents/devin) ## Devin Desktop [#devin-desktop] Abra as configurações de MCP e adicione um servidor, ou edite o `mcp_config.json`: ```json title="mcp_config.json" { "mcpServers": { "typestrict": { "serverUrl": "https://api.typestrict.ai/mcp" } } } ``` O Devin pede para você entrar no typestrict na primeira vez. O servidor local, depois de instalar a [CLI](/br/cli): `"typestrict": { "command": "typestrict", "args": ["mcp"] }`. ## Devin CLI [#devin-cli] ```bash devin mcp add typestrict https://api.typestrict.ai/mcp devin mcp login typestrict ``` O servidor local: `devin mcp add typestrict -- typestrict mcp`. ## Skills [#skills] O Devin lê skills de `.devin/skills` no repositório: ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .devin/skills && cp -r skills/typestrict-* .devin/skills/ ``` # Assistentes de IA (/br/agents) Um assistente pode conduzir o fluxo inteiro por você: enviar os dados, responder à revisão, iniciar o treino, acompanhá-lo até o resultado e ligar o modelo ao seu código. Todo treino diz do que precisa a seguir (`next_action`, veja [Treinos](/br/trainings)), então o assistente sempre sabe qual é o próximo passo. ## Servidor MCP remoto [#servidor-mcp-remoto] ```txt https://api.typestrict.ai/mcp ``` Nada para instalar: adicione a URL ao seu assistente e entre no typestrict quando ele pedir (OAuth). Assistentes que aceitam headers personalizados podem usar uma chave de API no lugar (`Authorization: Bearer ts_...`, das [Configurações](https://typestrict.ai/br/settings#api-keys)). Ele tem uma ferramenta para cada passo. Iniciar um treino sempre leva um orçamento e a sua confirmação, então nenhum crédito é gasto sem perguntar. O servidor remoto não lê o seu disco: o assistente envia arquivos de texto (CSV, JSON, texto) pelo conteúdo. Para arquivos grandes, Excel, PDF ou zip, envie pelo [dashboard](https://typestrict.ai/trainings/new) e deixe o assistente conduzir o treino a partir daí, ou use o servidor local. ## Servidor MCP local [#servidor-mcp-local] A [CLI do typestrict](/br/cli) inclui o mesmo servidor via stdio, `typestrict mcp`. Ele roda na sua máquina com a sua chave de API, então o assistente consegue enviar qualquer arquivo local e salvar o modelo no seu projeto. ```bash curl -fsSL https://typestrict.ai/install.sh | sh typestrict login # uma chave de API de https://typestrict.ai/br/settings#api-keys ``` | Assistente | Remoto (`https://api.typestrict.ai/mcp`) | Local (`typestrict mcp`) | | ------------------------------------- | ---------------------------------------- | ------------------------ | | [ChatGPT](/br/agents/chatgpt) | Sim, OAuth | Não | | [Claude](/br/agents/claude) | Claude.ai, Desktop e Claude Code | Claude Code | | [Cursor](/br/agents/cursor) | Sim | Sim | | [OpenAI Codex](/br/agents/codex) | Sim | Sim | | [GitHub Copilot](/br/agents/copilot) | VS Code e Copilot CLI | Sim | | [Antigravity](/br/agents/antigravity) | Sim | Sim | | [Devin Desktop](/br/agents/devin) | Sim | Sim | | [Outros](/br/agents/others) | Zed, Kiro, opencode, Cline | Sim | ## Skills [#skills] O [typestrict-lab/skills](https://github.com/typestrict-lab/skills) põe o seu assistente para trabalhar no que faz um modelo ser bom: ele confere e prepara os dados, revisa a proposta da agente e corrige antes do treino, e integra o resultado. As skills usam o servidor MCP (remoto ou local) e a CLI, e levam as [dicas para o melhor modelo](/br/best-results). ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ # Codex, Cursor, Copilot, Antigravity, opencode mkdir -p .claude/skills && cp -r skills/typestrict-* .claude/skills/ # Claude Code ``` A página de cada assistente diz onde ele lê as skills. ## Sem MCP [#sem-mcp] Qualquer assistente com terminal também pode rodar a CLI diretamente (`typestrict status --json`, `typestrict run`...). Adicione isto ao arquivo de instruções dele (`AGENTS.md`, `CLAUDE.md`...): ```md title="instruções typestrict" ## typestrict - O typestrict treina modelos de decisão pequenos nos nossos dados. Use a CLI do typestrict (instalação: curl -fsSL https://typestrict.ai/install.sh | sh). - Documentação para assistentes: https://docs.typestrict.ai/llms-full.txt. Leia antes do primeiro comando. - Conduza cada treino pelo seu `next_action` (`typestrict status --json`). - Iniciar um treino custa um crédito: mostre o custo e pergunte antes de `typestrict run`. - Nunca imprima a chave de API nem faça commit dela. ``` # Outros assistentes (/br/agents/others) Qualquer cliente MCP funciona com o servidor remoto, `https://api.typestrict.ai/mcp` (streamable HTTP, OAuth ou uma chave de API em `Authorization: Bearer ts_...`), ou com o local, o comando `typestrict mcp` via stdio. ```json title="Zed (settings.json)" { "context_servers": { "typestrict": { "url": "https://api.typestrict.ai/mcp" } } } ``` ```json title="Kiro (.kiro/settings/mcp.json)" { "mcpServers": { "typestrict": { "url": "https://api.typestrict.ai/mcp" } } } ``` ```json title="opencode (opencode.json)" { "mcp": { "typestrict": { "type": "remote", "url": "https://api.typestrict.ai/mcp" } } } ``` Entre com `opencode mcp auth typestrict`. ```json title="Cline (MCP settings)" { "mcpServers": { "typestrict": { "type": "streamableHttp", "url": "https://api.typestrict.ai/mcp" } } } ``` **Skills.** A maioria dos assistentes lê o formato aberto de skills em `.agents/skills`; veja o [typestrict-lab/skills](https://github.com/typestrict-lab/skills). **Para quem desenvolve clientes.** O servidor publica os seus metadados em `https://api.typestrict.ai/.well-known/oauth-protected-resource/mcp` (RFC 9728) e responde a uma requisição sem token com um 401 que aponta para eles. O servidor de autorização é `https://typestrict.ai`: PKCE (S256), o parâmetro `resource` (RFC 8707), Client ID Metadata Documents ou registro dinâmico de cliente, e o parâmetro `iss` no redirect (RFC 9207). # Get the balance (/br/api/credits/get-the-balance) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List the credit history (/br/api/credits/list-the-credit-history) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Confirm an upload (/br/api/datasets/confirm-an-upload) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Copy a dataset (/br/api/datasets/copy-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Create a dataset (/br/api/datasets/create-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Delete a dataset (/br/api/datasets/delete-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a dataset (/br/api/datasets/get-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get the next example to label (/br/api/datasets/get-the-next-example-to-label) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Label an example (/br/api/datasets/label-an-example) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List a dataset's sources (/br/api/datasets/list-a-datasets-sources) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List datasets (/br/api/datasets/list-datasets) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Structure a dataset (/br/api/datasets/structure-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Suggest decisions (/br/api/datasets/suggest-decisions) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Update a dataset (/br/api/datasets/update-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Health (/br/api/health/health) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Download a model (/br/api/models/download-a-model) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a model (/br/api/models/get-a-model) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a model's package (/br/api/models/get-a-models-package) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get the audit of a verdict (/br/api/models/get-the-audit-of-a-verdict) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List base models (/br/api/models/list-base-models) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List models (/br/api/models/list-models) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Replicate a recipe (/br/api/models/replicate-a-recipe) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Start a training (/br/api/models/start-a-training) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a published model (/br/api/public/get-a-published-model) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a GitHub repository (/br/api/sources/get-a-github-repository) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a Hugging Face dataset (/br/api/sources/get-a-hugging-face-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Search Hugging Face datasets (/br/api/sources/search-hugging-face-datasets) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List trainings (/br/api/trainings/list-trainings) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Autenticação (/br/authentication) Envie a chave como bearer token: ```http Authorization: Bearer ts_... ``` Uma chave age como a conta que a criou: vê e gasta o que essa conta vê e gasta. Crie e apague chaves em [Configurações → Chaves de API](https://typestrict.ai/br/settings#api-keys); apagar uma chave a desliga na hora. ## Assistentes de IA [#assistentes-de-ia] Assistentes conectados ao [servidor MCP remoto](/br/agents) entram com OAuth no lugar da chave: você entra no typestrict uma vez e autoriza o assistente, e ele recebe um token que age como a sua conta. Para desconectar um, remova o conector no assistente. ## Guarde em segredo [#guarde-em-segredo] * Leia de uma variável de ambiente ou de um cofre de segredos, nunca do código ou de um repositório. * Chame a API dos seus servidores. Uma chave no navegador ou num app é uma chave que qualquer um copia. * Uma chave por lugar que a usa, para que revogar uma não pare as outras. As chaves começam com `ts_`, para que scanners de segredos reconheçam uma que vazou. ## Erros [#erros] Uma chave ausente, desconhecida, desligada ou vencida responde `401`: ```json { "error": "unauthorized", "message": "unauthorized" } ``` Todo erro tem o mesmo formato: um código `error` estável para decidir o que fazer e uma `message` para pessoas. # Modelos base (/br/base-models) O seu modelo não é treinado do zero: ele parte de um **modelo base**, um encoder que já lê linguagem e toma decisões tipadas, e aprende a sua decisão em cima dele. Todo modelo base é nosso, com o nome `TS-{base}-{tamanho}`, aberto e liberado para uso comercial (Apache-2.0). `GET /v1/encoders` lista todos, com o que dá para escolher agora. | Modelo base | `encoder` | Tamanho | Idiomas | Contexto | Decision Index 0.3 | Treino | | ---------------------------------------------------------------------------------- | ----------------- | ------- | ------- | ------------ | ------------------ | ---------- | | [TS-moBERTo-150M](https://huggingface.co/typestrict/TS-moBERTo-150M) (recomendado) | `ts-moberto-150m` | 150M | EN, PT | 8.192 tokens | 31,20 / 33,89 | Disponível | | [TS-Ettin-150M](https://huggingface.co/typestrict/TS-Ettin-150M) | `ts-ettin-150m` | 150M | EN | 8.192 tokens | 31,96 / 34,78 | Disponível | | [TS-Ettin-68M](https://huggingface.co/typestrict/TS-Ettin-68M) | `ts-ettin-68m` | 68M | EN | 8.192 tokens | 27,61 / 30,46 | Disponível | | [TS-Ettin-32M](https://huggingface.co/typestrict/TS-Ettin-32M) | `ts-ettin-32m` | 32M | EN | 8.192 tokens | 19,70 / 22,45 | Disponível | | [TS-Ettin-17M](https://huggingface.co/typestrict/TS-Ettin-17M) | `ts-ettin-17m` | 17M | EN | 8.192 tokens | 15,76 / 18,52 | Disponível | O índice público do [Decision Index](https://github.com/apolinario/decision-index) 0.3, na rodada do nosso lab: o encoder sozinho, depois com os especialistas de código e de cálculo que vêm com os modelos publicados. Medido em benchmarks públicos, não na sua tarefa: o seu modelo é medido nos seus exemplos, contra o Jev ([o cálculo de reembolso](/br/refund)). O contexto é quanto texto um exemplo comporta; exemplos maiores são recusados, nunca cortados. ## TS-moBERTo-150M [#ts-moberto-150m] A nossa base padrão, em inglês e português, feita para decisões tipadas (`choice`, `noul`, `score`, com probabilidades e uma confiança) em CPU. Ela parte do [moBERTo](https://huggingface.co/Tropic-AI/moBERTo-orig-tokenizer) (Apache-2.0) e foi publicada antes como [Dinah-1](https://huggingface.co/Lukitaduarte/dinah-1), cuja rodada oficial do Decision Index marcou **34,32**, com os resultados brutos publicados para auditoria. Em decisões tipadas separadas para teste (1.000 itens cada): 0,790 de acurácia em inglês e 0,780 em português. ## TS-Ettin [#ts-ettin] A mesma receita sobre os [rerankers Ettin](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1) (Apache-2.0), em quatro tamanhos, só em inglês. O de 150M é a base mais forte no índice; os menores trocam pontos por velocidade e memória, para celulares, navegadores e volumes altos. A confiança deles ainda não foi calibrada; o seu modelo treinado continua medido do mesmo jeito. ## Com o que foram treinados [#com-o-que-foram-treinados] Os cinco seguem a mesma receita, nos mesmos dados, em duas etapas (2.048 tokens, depois 8.192) e a média das duas. Cada fonte com a licença que o seu próprio card declara. Fontes sob CC BY-SA e CDLA-Sharing são usadas só no treino e não são redistribuídas. | Área | Fontes | | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Decisões tipadas | ZefanCai/Open-Jev (CC0-1.0), LocalLLaMA/typed-decisions (Apache-2.0), typed-decisions-pt traduzido com Qwen3-4B (Apache-2.0), tasksource/procedural-typed-decisions (Apache-2.0) | | Intenções e atendimento ao cliente | AmazonScience/massive (CC BY 4.0), Bitext customer support (CDLA-Sharing-1.0), BANKING77 (CC BY 4.0), CLINC150 (CC BY 3.0), FAQ_BACEN (Apache-2.0) | | Inferência e checagem de fatos | WANLI (CC BY 4.0), SNLI (CC BY-SA 4.0), HoVer (CC BY-SA 4.0), FEVER-NLI (MIT; FEVER e Wikipedia CC BY-SA 3.0), ContractNLI (CC BY 4.0), bAbI-NLI (BSD), FaQuAD-NLI (CC BY 4.0), ExtraGLUE RTE e COPA em português (MIT) | | Raciocínio e conhecimento | CommonsenseQA (MIT), Cosmos QA (CC BY 4.0), BoolQ (CC BY-SA 3.0), HellaSwag (MIT), WinoGrande (Apache-2.0), split de treino do ARC (CC BY-SA 4.0), QASC (CC BY 4.0), StrategyQA (MIT), tarefas do BIG-bench sem BBH (Apache-2.0), MMLU auxiliary train, partes ARC e OpenBookQA (MIT), GSM8K (MIT), CLadder (MIT) | | Saúde, finanças e direito | PubMedQA (MIT), MedMCQA (Apache-2.0), twitter-financial-news-sentiment (MIT), financial-tweets-sentiment (MIT), NOSIBLE financial-sentiment (ODC-By), FinQA hallucination detection (MIT), pyRis/SEntFiN (MIT), CUAD (CC BY 4.0), jurisprudencias_br (CC BY 4.0), IBM Claim Stance (CC BY 3.0) | | Sentimento, emoção e moderação | GoEmotions (Apache-2.0), Civil Comments (CC0-1.0), iSarcasmEval (MIT), B2W-Reviews01 (CC BY 4.0), multilingual-sentiments em português (Apache-2.0) | | Busca e alucinação | ESCI (Apache-2.0), HaluEval (Apache-2.0), RAGTruth (MIT), CNN/DailyMail (Apache-2.0), SQuAD 2.0 (CC BY-SA 4.0) | | Ferramentas | glaive-function-calling-v2 (Apache-2.0), ToolACE (Apache-2.0), hermes-function-calling-v1 (Apache-2.0), nvidia/When2Call (CC BY 4.0) | | Phishing | LLMGen-Phishing-Email-Dataset (Apache-2.0), aura-phishing-email-corpus, parte SpamAssassin (CC BY 4.0) | | Xadrez | Lichess puzzles (CC0-1.0), google-deepmind/searchless_chess (Apache-2.0) | | Humor | newyorker_caption_contest, tarefa de correspondência (CC BY 4.0) | | Feito por nós | Traduções de inglês para português com opus-mt-tc-big-en-pt (CC BY 4.0); e-mails de phishing sintéticos escritos com gpt-oss-120b, rótulos definidos por código (Apache-2.0); residências sintéticas com eletrodomésticos, exemplos de alucinação em RAG e habilidades programáticas (aritmética, datas, unidades, ordenação, grafos, saída de código), gerados pelos nossos scripts (MIT e Apache-2.0) | Os blocos de treino foram checados contra as linhas públicas de teste do Decision Index (remoção de duplicatas exatas e quase duplicatas, e sobreposição de 8-gramas para os blocos mais novos). ## Qual escolher [#qual-escolher] * **Na dúvida, ou em português:** TS-moBERTo-150M, o padrão. É o mais forte nas nossas decisões tipadas separadas para teste (0,790 em inglês, 0,780 em português, contra 0,709 em inglês do TS-Ettin-150M). * **Em inglês, e você quer comparar:** TS-Ettin-150M, o mais alto no Decision Index. Treine os dois nos mesmos dados e fique com a versão que vencer nos seus exemplos separados para teste. * **Quando cada milissegundo ou megabyte conta:** TS-Ettin-68M, 32M ou 17M. Todo modelo base treina do mesmo jeito e é medido pela mesma regra, então testar outro é uma nova versão do mesmo treino. # Tirando o melhor modelo (/br/best-results) * **As suas categorias ganham.** O modelo supera o Jev com folga em decisões com as respostas da própria empresa (as suas filas, times, produtos, intenções): BANKING77 0,889 contra 0,797 de macro-F1, um conjunto de atendimento 0,998 contra 0,771. Em perguntas genéricas com pouco dado (o assunto de uma notícia, o tipo de cláusula de um contrato com algumas centenas de exemplos) o Jev já sabe muito e a margem é pequena. Monte a decisão em torno das suas respostas. * **Exemplos por resposta importam mais que o total.** Mire em centenas de exemplos rotulados por resposta quando você tiver. Os nossos modelos base são pré-treinados em decisões, o que ajuda mais com pouquíssimos exemplos; com muitos, quem decide são os seus dados. * **A resposta mais fraca define o nível.** Um modelo é tão bom quanto a sua pior resposta: uma resposta com poucos exemplos puxa o modelo inteiro para baixo. Junte respostas raras e parecidas, ou junte mais exemplos delas, antes de treinar. * **Respostas que não se sobrepõem, com descrição.** A descrição de cada resposta faz parte do que o modelo lê. Escreva de um jeito que uma pessoa nunca hesite entre duas. * **A entrada da produção.** Treine com o texto que existe no momento da decisão, nada que só se sabe depois (um campo "resolvido por" quando a pergunta é qual time resolve). * **Rótulos consistentes.** Ao rotular os exemplos de teste, o mesmo caso recebe sempre a mesma resposta: o modelo é medido contra essas respostas. ## Antes de enviar [#antes-de-enviar] Envie uma tabela limpa (CSV ou JSON lines), não a exportação bruta. O seu assistente de IA pode fazer isso por você com as [skills](/br/agents): 1. **Uma linha por exemplo**, com uma coluna de texto com tudo em que a decisão se baseia (assunto e corpo, ou os campos que uma pessoa leria) e nada mais. 2. **Uma grafia por resposta**: `Billing`, `billing ` e `Faturamento` são uma resposta só. Deixe de fora linhas vazias. 3. **Respostas raras resolvidas agora**: juntas com a resposta mais próxima, ou com mais exemplos. 4. **Sem vazamentos**: colunas ou texto que só existem depois da decisão. 5. **Sem duplicados exatos**, e nenhum exemplo com mais de uns 30.000 caracteres (eles são recusados, nunca cortados). 6. **Um objetivo preciso**: a pergunta e uma linha por resposta dizendo quando ela vale. Quanto mais preciso, melhor a primeira proposta. ## Conferindo a proposta [#conferindo-a-proposta] Assim que a proposta fica pronta, antes de rotular, passe por ela (a tela de Revisão, `typestrict review`, ou `structure.stats` na API) e mande o que mudar como feedback: 1. **Exemplos por resposta.** Centenas por resposta é onde o modelo fica bom, e uma resposta precisa de pelo menos 5 exemplos de teste para ser medida. Os exemplos de teste são 20% dos seus dados (até 2.000) quando eles vêm com resposta, ou 150 sorteados que você rotula quando não vêm: aí uma resposta com menos de uns 3% dos dados recebe menos de 5. Junte uma resposta rara com a mais próxima, ou adicione exemplos dela. 2. **Respostas que se sobrepõem.** Leia os exemplos de cada resposta. Se uma pessoa trocaria duas respostas, junte-as ou reescreva as descrições até a fronteira ficar clara. Quando os dados não tinham resposta, pouca concordância entre os pré-rotuladores aponta o mesmo problema. 3. **Rótulos que parecem errados.** Um exemplo cuja resposta não bate com o texto indica uma coluna de resposta ruidosa: corrija de onde vem a resposta. 4. **Todo aviso.** Cada um diz o que mudar. 5. **Duplicados e vazamentos.** O texto tem que ser o que existe no momento da decisão. 6. **A pergunta.** Decida com as respostas da sua empresa. Modelos grandes já respondem bem perguntas genéricas (assunto, sentimento); as suas filas, times e produtos são o que só os seus dados sabem. ## Quando não supera o Jev [#quando-não-supera-o-jev] A comparação diz o porquê (`model.jev.superiority.reason`): um ganho pequeno demais para ter certeza, ou uma resposta que fica atrás do Jev. Mais exemplos das respostas fracas, ou outro [modelo base](/br/base-models) nos mesmos dados, são as próximas tentativas. Toda versão é medida nos mesmos exemplos separados para teste, então as versões se comparam de forma justa. ## Em produção [#em-produção] Use a `confidence` do modelo para decidir o que automatizar e o que mandar para uma pessoa. O resultado mostra exatamente isso, a acurácia nas 80% respostas mais confiantes: comece automatizando acima de um limite e ajuste com o que você vir. Pergunte ao modelo a pergunta e as opções com que ele foi treinado, como estão no `decision_ai.json`. # CLI (/br/cli) Um binário para macOS, Linux e Windows que faz o que o dashboard faz. Código aberto: [typestrict-lab/cli](https://github.com/typestrict-lab/cli). ```bash curl -fsSL https://typestrict.ai/install.sh | sh # macOS e Linux; Windows: o zip da última release typestrict login # cole uma chave de API, ou defina TYPESTRICT_API_KEY ``` ## O fluxo [#o-fluxo] ```bash typestrict train tickets.csv --goal "Qual time atende o ticket?" --watch # envia, mascara, lê typestrict structure # a agente transforma os dados em exemplos de treino typestrict review # a proposta dela: a pergunta, as respostas, os avisos typestrict structure --feedback "..." # ajuste typestrict label # quando pedido, responda os exemplos de teste no terminal typestrict run --watch # mostra o custo e pergunta antes de gastar o crédito typestrict result # o veredito contra o Jev typestrict pull # decision_ai.json, tokenizer.json, onnx/model_8bit.onnx ``` | Comando | O que faz | | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | `train [--goal] [--question] [--hf org/nome:arquivo] [--github org/nome] [--no-anonymize] [--watch]` | Envia os dados e começa a preparar um treino. | | `status [] [--watch]` | Todos os treinos com o passo e a próxima ação, ou um deles. `--watch` acompanha e sai com 1 se falhar. | | `structure [--question] [--feedback]` | Roda a agente de estruturação, ou de novo com as decisões escolhidas ou o seu feedback. | | `suggest ` | Pede à agente decisões que esses dados ensinam. | | `review ` | Mostra a proposta da agente. | | `label ` | Responde os exemplos de teste um a um. | | `encoders` | Os modelos base e quais dá para escolher. | | `credits` | O seu saldo. | | `run [--base ts-moberto-150m] [--yes] [--watch]` | Começa o treino. Pergunta antes de gastar, a menos que use `--yes`. | | `result ` | O veredito contra o Jev e até quando os arquivos podem ser baixados. | | `pull [--dir]` | Baixa o pacote do modelo. | | `mcp` | O servidor MCP via stdio, para assistentes. | Todo comando aceita `--json` para saída legível por máquina, e cabe em scripts e CI. ## Para assistentes [#para-assistentes] ```bash typestrict mcp ``` O mesmo fluxo como ferramentas MCP: `list_trainings`, `get_training`, `wait_for_change`, `create_dataset`, `structure_dataset`, `suggest_decisions`, `next_example_to_label`, `label_example`, `list_base_models`, `get_credits`, `quote_training`, `start_training`, `get_model`, `get_audit`, `download_model`. Começar um treino sempre passa por um orçamento e a confirmação dele, então um assistente nunca gasta crédito sem perguntar. As mesmas ferramentas são servidas remotamente em `https://api.typestrict.ai/mcp`, sem nada para instalar. O servidor local é para quando o assistente deve enviar arquivos de qualquer tipo do seu disco e salvar o modelo no seu projeto. A configuração de cada assistente: [Assistentes de IA](/br/agents). # Rode em qualquer lugar (/br/deploy) O container está sendo construído; hoje um modelo é baixado como ONNX, pesos e pacote. Esta página é a especificação dele. O runtime de serving é open source (Apache-2.0). Cada modelo também sai como uma imagem de container: o modelo, um runtime de CPU (ONNX Runtime) e um servidor HTTP, nada para configurar. Ele fala a mesma API de decisão do Jev, então trocar o Jev pelo seu próprio modelo é trocar uma URL base. | Endpoint | O que faz | | -------------------- | ------------------------------------------------------------------------------ | | `POST /v1/systemone` | Responde perguntas sobre um texto, no formato de requisição e resposta do Jev. | | `GET /v1/models` | O modelo que está dentro, pelo nome. | | `GET /healthz` | `ok` quando está pronto, para health checks. | | Variável | Padrão | O que faz | | ------------------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `PORT` | `8080` | A porta em que escuta (o Cloud Run e o Lambda definem). | | `TYPESTRICT_TOKEN` | nenhum | Quando definida, toda requisição precisa levar `Authorization: Bearer `. Prefira a autenticação da sua própria plataforma (Cloud Run IAM, Lambda IAM) quando tiver. | Sem GPU, sem acesso à internet e sem chamadas para nós: requisições e dados ficam na sua infraestrutura. ## Docker [#docker] ```bash typestrict pull --container # ou: docker load -i .tar (link de download na página do modelo) docker run -p 8080:8080 typestrict/ ``` ```bash curl http://localhost:8080/v1/systemone -H "Content-Type: application/json" -d '{ "model": "ticket-router", "state": "Fui cobrado duas vezes. Por favor, me ajudem.", "questions": { "team": { "type": "choice", "instructions": "Qual time atende o ticket?", "criteria": { "billing": "Pagamentos e faturas", "support": "Todo o resto" } } } }' # uma resposta tem esta cara: # { "model": "ticket-router", "answers": { "team": { "type": "choice", "choice": "billing", "confidence": 0.97, # "probabilities": { "billing": 0.97, "support": 0.03 } } }, "usage": { "input_tokens": 41, "output_tokens": 0 } } ``` ## Google Cloud Run [#google-cloud-run] O Cloud Run roda imagens do Artifact Registry. Copie a imagem para lá e depois faça o deploy: ```bash typestrict pull --to us-docker.pkg.dev///ticket-router gcloud run deploy ticket-router \ --image us-docker.pkg.dev///ticket-router \ --region us-central1 --cpu 1 --memory 1Gi \ --no-allow-unauthenticated ``` `--no-allow-unauthenticated` mantém o serviço privado: quem chama precisa de um identity token de uma service account com o papel `roles/run.invoker`. Defina `--min-instances 1` se a primeira requisição depois de um período parado precisar ser rápida. ## AWS Lambda [#aws-lambda] A imagem traz o [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter), então a mesma imagem roda no Lambda sem mudanças. O Lambda roda imagens do ECR na mesma conta e região: ```bash typestrict pull --to .dkr.ecr.us-east-1.amazonaws.com/ticket-router aws lambda create-function --function-name ticket-router \ --package-type Image \ --code ImageUri=.dkr.ecr.us-east-1.amazonaws.com/ticket-router:latest \ --role arn:aws:iam:::role/ \ --memory-size 2048 --timeout 30 aws lambda create-function-url-config --function-name ticket-router --auth-type AWS_IAM ``` No Lambda, a CPU cresce com a memória: 2 GB é um bom começo. A primeira requisição depois de um cold start carrega o modelo. ## Firebase [#firebase] As Firebase Functions não rodam imagens próprias, então o modelo roda no Cloud Run (acima) e o Firebase chega até ele: * **Hosting:** direcione um caminho direto para o serviço do Cloud Run com um rewrite no `firebase.json`: ```json { "hosting": { "rewrites": [{ "source": "/api/decide", "run": { "serviceId": "ticket-router", "region": "us-central1" } }] } } ``` * **Functions:** chame o serviço do Cloud Run a partir da sua função com um identity token, como qualquer outra API HTTP. ## Kubernetes [#kubernetes] ```yaml apiVersion: apps/v1 kind: Deployment metadata: { name: ticket-router } spec: replicas: 2 selector: { matchLabels: { app: ticket-router } } template: metadata: { labels: { app: ticket-router } } spec: containers: - name: model image: /ticket-router ports: [{ containerPort: 8080 }] resources: { requests: { cpu: "1", memory: 1Gi }, limits: { memory: 2Gi } } readinessProbe: { httpGet: { path: /healthz, port: 8080 } } livenessProbe: { httpGet: { path: /healthz, port: 8080 }, periodSeconds: 30 } --- apiVersion: v1 kind: Service metadata: { name: ticket-router } spec: selector: { app: ticket-router } ports: [{ port: 80, targetPort: 8080 }] ``` O modelo não guarda estado, então escala horizontalmente com réplicas (ou um HorizontalPodAutoscaler por CPU). # Glossário (/br/glossary) **Acurácia.** A proporção de respostas certas. Simples, mas esconde as respostas raras: um modelo que sempre responde a mais comum pode tirar uma nota alta. **Anonimização (mascaramento).** Trocar os dados pessoais dos seus arquivos (nomes, e-mails, telefones, documentos, números de cartão) por marcadores como `[EMAIL]`, antes que qualquer outra coisa os leia. **Chave de API.** Um segredo que deixa o seu código chamar a API como a sua conta. As nossas começam com `ts_`. **Modelo base (encoder).** O modelo de onde o seu modelo parte. Ele já lê linguagem; o treino ensina a sua decisão a ele. Veja [Modelos base](/br/base-models). **Bootstrap.** Medir de novo em muitas reamostragens dos mesmos exemplos de teste, para ver quanto um resultado poderia variar por acaso. O [cálculo de reembolso](/br/refund) usa 2.000 delas. **Brier score e Brier skill.** O quanto as probabilidades estão longe do que aconteceu. O Brier skill transforma isso numa nota de 0 a 1 em que maior é melhor: um modelo que diz 90% e acerta pontua mais que um que diz 51% e acerta. **Calibração.** Se "80% de certeza" acerta cerca de 80% das vezes. Num modelo calibrado, dá para confiar na confiança para decidir o que automatizar. **Confiança.** O quanto o modelo tem certeza da resposta que escolheu, de 0 a 1. **Contexto.** Quanto texto cabe num exemplo, em tokens (pedaços de palavras). Depende do modelo base. **Crédito.** O que um treino custa. Ele volta se o modelo não superar o Jev ou se o treino falhar. **API de decisão.** Uma API que responde perguntas sobre um texto com um resultado tipado em vez de texto livre: um `choice` entre opções, um `noul` (verdadeiro ou falso, como probabilidade) ou um `score` numa escala, cada um com probabilidades. A API do Jev, que o container do seu modelo também fala, é uma delas. **Encoder.** Um modelo que lê um texto e o representa, sem escrever texto. Pequeno, rápido e barato de rodar numa CPU, por isso serve para decisões. **Exemplos separados (de teste).** Exemplos separados antes do treino e nunca vistos pelo modelo, para que a medida seja honesta. **Jev.** O modelo de referência do mercado para decisões, um modelo geral grande. Comparamos todo modelo contra ele nos seus próprios exemplos. **Macro-F1.** O F1 (um equilíbrio entre precisão e revocação) de cada resposta, com média em que todas as respostas pesam igual. Respostas raras contam tanto quanto as comuns. **Modelo multitarefa.** Um modelo que toma várias decisões sobre a mesma entrada. Medido por tarefa contra o seu modelo base. **ONNX.** Um formato aberto de arquivo para modelos. Roda em CPUs em qualquer linguagem pelo ONNX Runtime, em servidores, navegadores e celulares. **Quantização (8 bits).** Guardar os números do modelo com menos bits. Menor e mais rápido, com perda mínima. **Acurácia seletiva.** Acurácia só nas respostas mais confiantes (80% delas na garantia): o que você obtém ao automatizar essas e mandar o resto para uma pessoa. **Agente de estruturação.** A nossa agente que lê os seus dados mascarados e os transforma em exemplos de treino para a decisão que você quer. **F1 da pior classe.** O F1 da resposta que o modelo trata pior. Impede que uma média esconda uma resposta que desabou. # Introdução (/br) O typestrict treina um modelo de decisão pequeno nos seus dados: ele lê um ticket, uma mensagem ou um documento e responde com uma decisão estruturada e tipada (um rótulo, um sim ou não, uma nota), no mesmo formato de resposta do Jev, o modelo de referência do mercado. Se o seu modelo não superar o Jev em exemplos que ele nunca viu no treino, o crédito volta. ## Como um treino acontece [#como-um-treino-acontece] Todo treino passa por cinco passos, igual no dashboard, na API e nos assistentes: 1. **Dados**: você envia arquivos, conecta o Google Drive ou o OneDrive, ou parte de um dataset público. Os dados pessoais são mascarados antes de qualquer outra leitura. 2. **Revisão**: nossa agente organiza os dados em exemplos de treino. Você confere a proposta e ajusta. 3. **Modelo base**: você escolhe o modelo sobre o qual treinar, liberado para uso comercial, e confirma o custo. 4. **Treino**: nós treinamos e medimos contra o Jev. 5. **Resultado**: você baixa o modelo (ONNX e pesos) e usa onde quiser, sem GPU. ## Por onde começar [#por-onde-começar] # Limites (/br/limits) | Limite | Valor | | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | Tamanho de um arquivo | 200 MB | | Arquivos num dataset | 500 | | Fontes públicas (Hugging Face, GitHub) num dataset | 10 | | Decisões criadas a partir de um dataset | 12 | | Tamanho da pergunta de uma decisão | 500 caracteres | | Tamanho de um ajuste para a agente | 1.000 caracteres | | Texto de um exemplo | O contexto do modelo base (veja [Modelos base](/br/base-models)); exemplos mais longos são recusados, nunca cortados | | Exemplos de teste medidos contra o Jev | 20% dos exemplos rotulados, até 2.000 | | URL de upload | Válida por 15 minutos | | Links de download e de auditoria | Válidos por 15 minutos; peça um novo a qualquer momento enquanto os arquivos estiverem guardados | | Página de uma lista | 25 por padrão, até 100 | | Custo de um treino | 1 crédito, devolvido se o modelo não superar o Jev ou se o treino falhar | Imagens não são usadas nesta versão: elas aparecem em **Não usados**, com o motivo. # Início rápido (/br/quickstart) ## 1. Crie uma chave de API [#1-crie-uma-chave-de-api] Abra [Configurações → Chaves de API](https://typestrict.ai/br/settings#api-keys) e crie uma chave. Ela começa com `ts_` e aparece uma vez só: guarde num cofre de segredos ou numa variável de ambiente. ```bash export TYPESTRICT_API_KEY=ts_... ``` Confira: curl TypeScript Python ```bash curl https://api.typestrict.ai/v1/credits \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" ``` ```ts const res = await fetch("https://api.typestrict.ai/v1/credits", { headers: { Authorization: `Bearer ${process.env.TYPESTRICT_API_KEY}` }, }) console.log(await res.json()) // { balance: 1, per_model: 1 } ``` ```python import os, requests res = requests.get( "https://api.typestrict.ai/v1/credits", headers={"Authorization": f"Bearer {os.environ['TYPESTRICT_API_KEY']}"}, ) print(res.json()) # {'balance': 1, 'per_model': 1} ``` ## 2. Envie seus dados [#2-envie-seus-dados] Descreva os arquivos e a decisão que você quer. A resposta traz uma URL de upload por arquivo, válida por 15 minutos. ```bash curl https://api.typestrict.ai/v1/datasets \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "tickets de suporte", "goal": "Qual time atende o ticket?", "files": [{ "filename": "tickets.csv", "content_type": "text/csv", "size": 48213 }] }' # { "id": "", "uploads": [{ "file_id": "", "filename": "tickets.csv", "url": "https://..." }] } ``` Envie cada arquivo para a sua URL e confirme: ```bash curl -X PUT --upload-file tickets.csv "" curl -X POST https://api.typestrict.ai/v1/datasets//files//complete \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" ``` ## 3. Acompanhe o treino [#3-acompanhe-o-treino] Todo treino diz em que passo está e o que precisa a seguir: ```bash curl https://api.typestrict.ai/v1/trainings \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" # { "data": [{ "kind": "dataset", "id": "", "step": 1, "next_action": "wait", ... }], "next": null } ``` Enquanto `next_action` for `wait`, estamos lendo e mascarando os dados. Depois a agente estrutura e o treino segue: [Treinos](/br/trainings) lista cada próxima ação e a chamada que responde a ela. # Cálculo de reembolso (/br/refund) Todo modelo treinado numa decisão é medido contra o Jev, o modelo de referência do mercado, nos seus próprios exemplos. Se ele não superar o Jev, o crédito volta sozinho para o seu saldo. "Superar" não é "uma métrica por qualquer margem": o cálculo de reembolso pede um ganho que se sustente na reamostragem e nenhuma métrica que desabe. ## Os exemplos de teste [#os-exemplos-de-teste] Antes do treino, separamos exemplos que o modelo nunca vê: * **20% dos seus exemplos rotulados**, sorteados por resposta para que cada resposta mantenha a sua proporção, **até 2.000**. * Quando os seus dados não têm respostas, os exemplos que uma pessoa rotulou no passo de revisão. O sorteio usa uma semente do dataset, então toda versão de um modelo é medida nos mesmos exemplos. O Jev responde aos mesmos exemplos pela mesma pergunta: as respostas dele servem só para medir, nunca para treinar. ## Quatro métricas [#quatro-métricas] Cada sistema recebe quatro notas nos exemplos de teste, todas quanto maior, melhor: | Métrica | O que ela diz | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | | `macro_f1` | Com que frequência a resposta está certa, com todas as respostas pesando igual, para que uma resposta rara conte tanto quanto uma comum. | | `brier_skill` | Quão boas são as probabilidades: `1 - mean Brier / 2`, de 0 a 1. Premia estar confiante quando acerta e em dúvida quando erra. | | `selective_acc_80` | Acurácia nas 80% respostas mais confiantes: o que você obtém ao automatizar as confiantes e mandar o resto para uma pessoa. | | `worst_class_f1` | F1 da resposta mais fraca com 5 ou mais exemplos. Nenhuma resposta pode desabar. | ## A regra [#a-regra] O ganho ponderado sobre o Jev é ```text G = 0.5 × Δmacro_f1 + 0.3 × Δbrier_skill + 0.2 × Δselective_acc_80 ``` onde `Δ` é a nossa nota menos a do Jev. O modelo **supera o Jev** só se as duas condições valerem: 1. **O ganho é real.** Reamostramos os exemplos de teste 2.000 vezes (um bootstrap pareado: o mesmo sorteio para os dois sistemas) e recalculamos `G` a cada vez. O 5º percentil desses 2.000 valores precisa estar acima de zero: `G > 0` com 95% de confiança. 2. **Nada desaba.** Nenhuma métrica pode ficar abaixo da do Jev por mais que a sua margem: 0,02 para as três primeiras, 0,05 para `worst_class_f1`. Qualquer outro resultado é reembolso, empates incluídos. Quando as probabilidades empatam no topo, os dois sistemas recebem o mesmo benefício da dúvida: a resposta conta como certa se a correta estiver entre as empatadas. A semente do bootstrap vem do SHA-256 dos textos dos exemplos de teste. Mesmos exemplos, mesmas respostas, mesmos números, sempre. ## Verifique você mesmo [#verifique-você-mesmo] Cada modelo tem um arquivo de auditoria (`GET /v1/models/{id}/audit`): para cada exemplo de teste, o SHA-256 do seu texto, a resposta correta e as probabilidades dos dois sistemas, mais o relatório com todos os números acima. O verificador refaz o relatório inteiro com a biblioteca padrão do Python e falha se qualquer número for diferente: ```bash curl -O https://typestrict.ai/verify_audit.py python3 verify_audit.py audit.json ``` A auditoria não guarda nenhum texto seu, só hashes e probabilidades, então ela fica com o registro do modelo mesmo depois que os arquivos dele expiram (veja [Retenção](/br/retention)). ## Quando a garantia não se aplica [#quando-a-garantia-não-se-aplica] * **Várias decisões num só modelo** (um plano multitarefa): cada tarefa é medida contra o modelo base de onde partiu, não contra o Jev, e não há reembolso pelo resultado. * **Um treino que falha** também devolve o crédito, seja qual for o tipo de modelo. # Retenção (/br/retention) O registro de cada dataset e modelo fica: o nome, os números, o veredito contra o Jev e a [auditoria](/br/refund#verifique-você-mesmo) desse veredito. O que pode ser baixado ou usado para treinar é guardado por um tempo limitado. | O quê | Por quanto tempo | Depois | | ----------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | Upload original | Até ser mascarado | Apagado logo depois do mascaramento. Só a cópia mascarada é usada. | | Os arquivos de um modelo (ONNX, pesos, pacote, exemplos de teste) | 30 dias após o fim do treino | Apagados. O registro e a auditoria ficam. | | Um modelo que não superou o Jev | Na hora | Os arquivos são apagados quando sai o veredito: o crédito voltou, não há nada a entregar. | | Um modelo publicado | Até estar no seu Hugging Face | Os arquivos saem do nosso armazenamento; o seu repositório é onde ele vive e de onde é baixado. | | Os dados de um dataset | 90 dias após o último uso | Apagados, incluindo as cópias que guardamos de prévias e amostras. Começar um treino com ele, ou copiá-lo para ajustar, conta como uso e soma 90 dias. | | Um upload que nunca terminou, ou falhou | 30 dias | Apagado junto com o registro. | | Uma conta encerrada | 30 dias após o pedido | Tudo é apagado. Até lá você pode cancelar, e as suas chaves de API param na hora. | O dashboard mostra as datas: **Disponível até** em Modelos e Dados. A API devolve as datas em todo modelo (`files_expire_at`, e `files_deleted_at` depois que saíram) e dataset (`data_expire_at`, `data_deleted_at`). ## Depois que expira [#depois-que-expira] * Baixar um modelo expirado responde `410` com `"error": "expired"`. A página, as métricas e a auditoria dele ficam. * Dados expirados não podem começar um treino, ser estruturados, rotulados ou copiados (`410`). Para treinar de novo, envie de novo. * Baixe o seu modelo em até 30 dias do treino, ou publique no seu Hugging Face pela página dele. Registros de pagamento são guardados por 5 anos e logs de acesso por 6 meses, como exige a lei brasileira. # Segurança e privacidade (/br/security) ## Os seus arquivos [#os-seus-arquivos] * **Mascaramento primeiro.** Antes que qualquer outra coisa leia os seus dados, mascaramos os dados pessoais: nomes, e-mails, telefones, documentos como CPF e CNPJ, e números de cartão. O upload original é apagado assim que a cópia mascarada existe. * **A agente vê amostras, não arquivos.** A agente de estruturação (um modelo de linguagem acessado pelo OpenRouter) vê a forma dos seus dados e amostras mascaradas, nunca os arquivos brutos. * **As máquinas de treino são temporárias.** O treino roda em GPUs alugadas da vast.ai. Elas recebem só dados mascarados, e cada máquina é destruída quando a execução termina. * **O Jev só mede.** A comparação envia os exemplos de teste mascarados ao Jev pelo OpenRouter. As respostas dele servem para medir, nunca para treinar. * **A escolha de pular o mascaramento é sua.** Se você declarar que os seus arquivos não têm dados pessoais, o mascaramento é pulado, a seu pedido e sob a sua responsabilidade. ## O seu modelo [#o-seu-modelo] Depois do treino, o modelo roda onde você colocar: nos seus servidores, na sua nuvem, no navegador ou num celular. O que você pergunta a ele nunca volta para nós. É um arquivo, não um serviço do qual você depende. ## A sua conta [#a-sua-conta] * Senhas são guardadas só como hash; você também pode entrar com uma passkey, Google ou Hugging Face. * Chaves de API são guardadas só como hash SHA-256 e aparecem uma vez. Elas começam com `ts_`, para que scanners de segredos reconheçam uma que vazou. * Assistentes de IA no servidor MCP remoto só ganham acesso depois que você entra e permite (OAuth com PKCE); os tokens deles valem só para esse servidor e expiram em até uma hora, renovados enquanto a conexão durar. * Toda chamada é checada contra o dono: uma conta nunca lê os datasets ou modelos de outra. ## Por quanto tempo guardamos [#por-quanto-tempo-guardamos] Veja [Retenção](/br/retention). A [política de privacidade](https://typestrict.ai/br/privacy) é a versão completa e vinculante desta página, com a lista dos fornecedores que processam dados para nós. # Treinos (/br/trainings) Um treino é um dataset sendo preparado (passos 1 a 3) ou, depois que roda, um modelo (passos 4 e 5). Cada um traz `step` (1 a 5) e `next_action`, os mesmos dois campos que o dashboard, a CLI e os assistentes leem, para que qualquer um deles conduza o fluxo. ```json { "kind": "dataset", "id": "0199f0c4-…", "name": "tickets de suporte", "status": "ready", "step": 2, "next_action": "structure" } ``` ## Próximas ações [#próximas-ações] | `next_action` | O que significa | O que chamar | | ---------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | | `upload_files` | Faltam arquivos. | `PUT` de cada arquivo na sua URL, depois `POST /v1/datasets/{id}/files/{arquivo}/complete` | | `wait` | Estamos trabalhando nele. | Leia de novo em alguns segundos: `GET /v1/datasets/{id}` ou `GET /v1/models/{id}` | | `start_over` | Não conseguimos ler os dados. | Crie um dataset novo com os arquivos corrigidos | | `structure` | Os dados foram lidos e mascarados. | `POST /v1/datasets/{id}/structure`, ou `POST /v1/datasets/{id}/suggest` para ver decisões antes | | `pick_decisions` | A agente sugeriu decisões. | `POST /v1/datasets/{id}/structure` com `{ "questions": [...] }` | | `label_examples` | Os exemplos separados para o teste precisam de resposta. | `GET /v1/datasets/{id}/labels/next`, depois `POST /v1/datasets/{id}/labels/{tarefa}` com `{ "label": "..." }` | | `start_training` | Pronto para treinar. | `GET /v1/encoders`, depois `POST /v1/datasets/{id}/models` com `{ "encoder": "ts-moberto-150m" }` (1 crédito) | | `retry` | O treino falhou e o crédito voltou. | `POST /v1/datasets/{dataset}/models` de novo | | `download` | O modelo está pronto. | `GET /v1/models/{id}/download` devolve um link válido por 15 minutos, até `files_expire_at` | | `none` | Os arquivos do modelo saíram (expiraram, reembolso ou no seu Hugging Face). | Nada: o registro e a auditoria ficam ([Retenção](/br/retention)) | | `expired` | Os dados do dataset expiraram. | Envie de novo para treinar ([Retenção](/br/retention)) | Começar um treino sem créditos responde `402` com `"error": "no_credits"`. ## Páginas [#páginas] As listas vêm da mais nova para a mais antiga, uma página por vez: ```json { "data": [ ... ], "next": "6b3f…" } ``` Passe `limit` (de 1 a 100, 25 por padrão) e, para a página seguinte, `cursor` com o último `next`. Uma página continua igual enquanto treinos novos chegam no topo. `GET /v1/models` e `GET /v1/datasets` também aceitam `status` (`done` para modelos concluídos, `ready` para datasets estruturados). ```bash curl "https://api.typestrict.ai/v1/models?status=done&limit=10" \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" ``` # Antigravity (/es/agents/antigravity) Abre el administrador de MCP (`/mcp`) y agrega el servidor, o edita la configuración. Antigravity usa `serverUrl` para los servidores remotos: ```json title="~/.gemini/config/mcp_config.json (o .agents/mcp_config.json en un workspace)" { "mcpServers": { "typestrict": { "serverUrl": "https://api.typestrict.ai/mcp" } } } ``` Antigravity te pide iniciar sesión en typestrict la primera vez. Con una clave de API, agrega `"headers": { "Authorization": "Bearer ts_..." }`. El servidor local (después de `curl -fsSL https://typestrict.ai/install.sh | sh` y `typestrict login`): ```json { "mcpServers": { "typestrict": { "command": "typestrict", "args": ["mcp"] } } } ``` **Skills.** Antigravity lee las skills de `.agents/skills` en el workspace y de `~/.gemini/config/skills`: ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ ``` ¿Sigues en Gemini CLI (Gemini Code Assist Standard o Enterprise)? Usa el servidor local de la misma forma, en `mcpServers` dentro de `~/.gemini/settings.json`. # ChatGPT (/es/agents/chatgpt) 1. Abre [chatgpt.com/plugins](https://chatgpt.com/plugins), elige **+** y **Add custom MCP server**. 2. Ponle el nombre typestrict, usa la URL `https://api.typestrict.ai/mcp` y OAuth, y créalo como plugin. 3. Inicia sesión en typestrict y autoriza a ChatGPT. Eso es todo: ChatGPT ya ve todos los entrenamientos de tu cuenta. Los servidores MCP personalizados están disponibles en ChatGPT Business, Enterprise y Edu, en la web. ChatGPT solo se conecta con OAuth (sin claves de API). Luego pide: "Entrena un modelo con esta hoja de cálculo que decida qué equipo atiende un ticket." ChatGPT envía los archivos de texto (CSV, JSON, texto) por su contenido; para Excel, PDF, zip o archivos grandes, súbelos en el [panel](https://typestrict.ai/trainings/new) y pídele a ChatGPT que siga el entrenamiento desde ahí. **Skills.** Agrega la guía de [typestrict-lab/skills](https://github.com/typestrict-lab/skills) a las instrucciones del proyecto o del GPT, o dale el enlace de la documentación (`https://docs.typestrict.ai/llms-full.txt`). # Claude (/es/agents/claude) ## Claude.ai y Claude Desktop [#claudeai-y-claude-desktop] 1. En **Customize → Connectors**, elige **Add custom connector**. En los planes Team y Enterprise, lo agrega un owner en **Organization settings → Connectors**. 2. Ponle el nombre typestrict y usa la URL `https://api.typestrict.ai/mcp`. 3. Inicia sesión en typestrict y autoriza a Claude. El mismo conector funciona en Claude Desktop y en el celular. Claude envía los archivos de texto (CSV, JSON, texto) por su contenido; para Excel, PDF, zip o archivos grandes, súbelos en el [panel](https://typestrict.ai/trainings/new) y pídele a Claude que siga el entrenamiento desde ahí. **Skills.** Comprime en zip una carpeta de [typestrict-lab/skills](https://github.com/typestrict-lab/skills) (el zip contiene `typestrict-train/SKILL.md`) y súbela en **Customize → Skills**. ## Claude Code [#claude-code] ```bash claude mcp add --transport http typestrict https://api.typestrict.ai/mcp ``` Luego ejecuta `/mcp` en Claude Code e inicia sesión en typestrict. Con una clave de API en lugar de OAuth: ```bash claude mcp add --transport http typestrict https://api.typestrict.ai/mcp --header "Authorization: Bearer $TYPESTRICT_API_KEY" ``` Para enviar archivos locales de cualquier tipo y guardar el modelo en tu proyecto, usa el servidor local: ```bash curl -fsSL https://typestrict.ai/install.sh | sh && typestrict login claude mcp add typestrict -- typestrict mcp ``` Agrega `--scope project` para compartir el servidor con tu equipo en `.mcp.json`. Skills: ```bash git clone https://github.com/typestrict-lab/skills.git && cp -r skills/typestrict-* ~/.claude/skills/ ``` Luego pide: "Entrena un modelo con `data/tickets.csv` que decida qué equipo atiende un ticket, e intégralo en `src/router.ts`." # OpenAI Codex (/es/agents/codex) ```bash codex mcp add typestrict --url https://api.typestrict.ai/mcp codex mcp login typestrict ``` La CLI, la extensión para IDE y la app de Codex comparten la configuración. Con una clave de API en lugar de OAuth: ```toml title="~/.codex/config.toml" [mcp_servers.typestrict] url = "https://api.typestrict.ai/mcp" bearer_token_env_var = "TYPESTRICT_API_KEY" ``` Para enviar archivos locales de cualquier tipo, usa el servidor local (después de `curl -fsSL https://typestrict.ai/install.sh | sh` y `typestrict login`): ```bash codex mcp add typestrict -- typestrict mcp ``` **Skills.** Codex lee las skills de `.agents/skills` en tu repositorio y de `~/.agents/skills`: ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ ``` El sandbox de Codex bloquea la red por defecto: permítela para la sesión, o aprueba las llamadas a `api.typestrict.ai` cuando Codex pregunte. # GitHub Copilot (/es/agents/copilot) ## VS Code [#vs-code] Ejecuta **MCP: Add Server** desde la Command Palette, elige HTTP y usa `https://api.typestrict.ai/mcp`, o: ```bash code --add-mcp '{"name":"typestrict","type":"http","url":"https://api.typestrict.ai/mcp"}' ``` VS Code te pide iniciar sesión en typestrict la primera vez que Copilot lo usa. El servidor local: ```bash code --add-mcp '{"name":"typestrict","type":"stdio","command":"typestrict","args":["mcp"]}' ``` ## Copilot CLI [#copilot-cli] ```bash copilot mcp add --transport http typestrict https://api.typestrict.ai/mcp ``` Inicia sesión con `/mcp auth typestrict`, o agrega `--header "Authorization: Bearer $TYPESTRICT_API_KEY"`. El servidor local: `copilot mcp add typestrict -- typestrict mcp`. ## Skills [#skills] Copilot lee las skills de `.github/skills` o `.agents/skills` en el repositorio, y de `~/.copilot/skills`: ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ ``` # Cursor (/es/agents/cursor) ```json title=".cursor/mcp.json (o ~/.cursor/mcp.json para todos los proyectos)" { "mcpServers": { "typestrict": { "url": "https://api.typestrict.ai/mcp" } } } ``` Cursor te pide iniciar sesión en typestrict la primera vez que usa el servidor. Usa OAuth aquí: Cursor puede ignorar un header `Authorization` configurado cuando el servidor ofrece inicio de sesión. Para enviar archivos locales de cualquier tipo, usa el servidor local (después de `curl -fsSL https://typestrict.ai/install.sh | sh` y `typestrict login`): ```json title=".cursor/mcp.json" { "mcpServers": { "typestrict": { "type": "stdio", "command": "typestrict", "args": ["mcp"] } } } ``` **Skills.** Cursor lee las skills de `.agents/skills` y `.cursor/skills` (y de las mismas carpetas en tu home): ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ ``` # Devin Desktop (/es/agents/devin) ## Devin Desktop [#devin-desktop] Abre la configuración de MCP y agrega un servidor, o edita `mcp_config.json`: ```json title="mcp_config.json" { "mcpServers": { "typestrict": { "serverUrl": "https://api.typestrict.ai/mcp" } } } ``` Devin te pide iniciar sesión en typestrict la primera vez. El servidor local, después de instalar la [CLI](/es/cli): `"typestrict": { "command": "typestrict", "args": ["mcp"] }`. ## Devin CLI [#devin-cli] ```bash devin mcp add typestrict https://api.typestrict.ai/mcp devin mcp login typestrict ``` El servidor local: `devin mcp add typestrict -- typestrict mcp`. ## Skills [#skills] Devin lee las skills de `.devin/skills` en el repositorio: ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .devin/skills && cp -r skills/typestrict-* .devin/skills/ ``` # Asistentes de IA (/es/agents) Un asistente puede hacer todo el flujo por ti: enviar los datos, responder la revisión, iniciar el entrenamiento, seguirlo hasta el resultado y conectar el modelo a tu código. Cada entrenamiento dice qué necesita a continuación (`next_action`, ver [Entrenamientos](/es/trainings)), así que el asistente siempre sabe cuál es el próximo paso. ## Servidor MCP remoto [#servidor-mcp-remoto] ```txt https://api.typestrict.ai/mcp ``` Nada que instalar: agrega la URL a tu asistente e inicia sesión en typestrict cuando te lo pida (OAuth). Los asistentes que aceptan headers personalizados pueden usar una clave de API en su lugar (`Authorization: Bearer ts_...`, de [Configuración](https://typestrict.ai/es/settings#api-keys)). Tiene una herramienta para cada paso; iniciar un entrenamiento siempre lleva una cotización y tu confirmación, así que no se gasta ningún crédito sin preguntar. El servidor remoto no puede leer tu disco: el asistente envía los archivos de texto (CSV, JSON, texto) por su contenido. Para archivos grandes, Excel, PDF o zip, súbelos en el [panel](https://typestrict.ai/trainings/new) y deja que el asistente siga el entrenamiento desde ahí, o usa el servidor local. ## Servidor MCP local [#servidor-mcp-local] La [CLI de typestrict](/es/cli) incluye el mismo servidor por stdio, `typestrict mcp`. Corre en tu máquina con tu clave de API, así que el asistente puede enviar cualquier archivo local y guardar el modelo en tu proyecto. ```bash curl -fsSL https://typestrict.ai/install.sh | sh typestrict login # una clave de API de https://typestrict.ai/settings#api-keys ``` | Asistente | Remoto (`https://api.typestrict.ai/mcp`) | Local (`typestrict mcp`) | | ------------------------------------- | ---------------------------------------- | ------------------------ | | [ChatGPT](/es/agents/chatgpt) | Sí, OAuth | No | | [Claude](/es/agents/claude) | Claude.ai, Desktop y Claude Code | Claude Code | | [Cursor](/es/agents/cursor) | Sí | Sí | | [OpenAI Codex](/es/agents/codex) | Sí | Sí | | [GitHub Copilot](/es/agents/copilot) | VS Code y Copilot CLI | Sí | | [Antigravity](/es/agents/antigravity) | Sí | Sí | | [Devin Desktop](/es/agents/devin) | Sí | Sí | | [Otros](/es/agents/others) | Zed, Kiro, opencode, Cline | Sí | ## Skills [#skills] [typestrict-lab/skills](https://github.com/typestrict-lab/skills) pone a tu asistente a trabajar en lo que hace bueno a un modelo: revisa y prepara los datos, revisa la propuesta de la agente y la corrige antes de entrenar, e integra el resultado. Usan el servidor MCP (remoto o local) y la CLI, y traen los [consejos para el mejor modelo](/es/best-results). ```bash git clone https://github.com/typestrict-lab/skills.git mkdir -p .agents/skills && cp -r skills/typestrict-* .agents/skills/ # Codex, Cursor, Copilot, Antigravity, opencode mkdir -p .claude/skills && cp -r skills/typestrict-* .claude/skills/ # Claude Code ``` La página de cada asistente dice dónde lee las skills. ## Sin MCP [#sin-mcp] Cualquier asistente con terminal también puede ejecutar la CLI directamente (`typestrict status --json`, `typestrict run`...). Agrega esto a su archivo de instrucciones (`AGENTS.md`, `CLAUDE.md`...): ```md title="instrucciones typestrict" ## typestrict - typestrict entrena modelos de decisión pequeños con nuestros datos. Usa la CLI de typestrict (instalación: curl -fsSL https://typestrict.ai/install.sh | sh). - Documentación para asistentes: https://docs.typestrict.ai/llms-full.txt. Léela antes del primer comando. - Conduce cada entrenamiento por su `next_action` (`typestrict status --json`). - Iniciar un entrenamiento cuesta un crédito: muestra el costo y pregunta antes de `typestrict run`. - Nunca imprimas la clave de API ni la incluyas en un commit. ``` # Otros asistentes (/es/agents/others) Cualquier cliente MCP funciona con el servidor remoto, `https://api.typestrict.ai/mcp` (streamable HTTP, OAuth o una clave de API en `Authorization: Bearer ts_...`), o con el local, el comando `typestrict mcp` por stdio. ```json title="Zed (settings.json)" { "context_servers": { "typestrict": { "url": "https://api.typestrict.ai/mcp" } } } ``` ```json title="Kiro (.kiro/settings/mcp.json)" { "mcpServers": { "typestrict": { "url": "https://api.typestrict.ai/mcp" } } } ``` ```json title="opencode (opencode.json)" { "mcp": { "typestrict": { "type": "remote", "url": "https://api.typestrict.ai/mcp" } } } ``` Inicia sesión con `opencode mcp auth typestrict`. ```json title="Cline (MCP settings)" { "mcpServers": { "typestrict": { "type": "streamableHttp", "url": "https://api.typestrict.ai/mcp" } } } ``` **Skills.** La mayoría de los asistentes lee el formato abierto de skills desde `.agents/skills`; ver [typestrict-lab/skills](https://github.com/typestrict-lab/skills). **Para desarrolladores de clientes.** El servidor publica sus metadatos en `https://api.typestrict.ai/.well-known/oauth-protected-resource/mcp` (RFC 9728) y responde a una solicitud sin token con un 401 que apunta a ellos. El servidor de autorización es `https://typestrict.ai`: PKCE (S256), el parámetro `resource` (RFC 8707), Client ID Metadata Documents o registro dinámico de clientes, y el parámetro `iss` en la redirección (RFC 9207). # Get the balance (/es/api/credits/get-the-balance) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List the credit history (/es/api/credits/list-the-credit-history) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Confirm an upload (/es/api/datasets/confirm-an-upload) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Copy a dataset (/es/api/datasets/copy-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Create a dataset (/es/api/datasets/create-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Delete a dataset (/es/api/datasets/delete-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a dataset (/es/api/datasets/get-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get the next example to label (/es/api/datasets/get-the-next-example-to-label) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Label an example (/es/api/datasets/label-an-example) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List a dataset's sources (/es/api/datasets/list-a-datasets-sources) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List datasets (/es/api/datasets/list-datasets) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Structure a dataset (/es/api/datasets/structure-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Suggest decisions (/es/api/datasets/suggest-decisions) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Update a dataset (/es/api/datasets/update-a-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Health (/es/api/health/health) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Download a model (/es/api/models/download-a-model) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a model (/es/api/models/get-a-model) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a model's package (/es/api/models/get-a-models-package) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get the audit of a verdict (/es/api/models/get-the-audit-of-a-verdict) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List base models (/es/api/models/list-base-models) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List models (/es/api/models/list-models) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Replicate a recipe (/es/api/models/replicate-a-recipe) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Start a training (/es/api/models/start-a-training) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a published model (/es/api/public/get-a-published-model) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a GitHub repository (/es/api/sources/get-a-github-repository) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Get a Hugging Face dataset (/es/api/sources/get-a-hugging-face-dataset) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Search Hugging Face datasets (/es/api/sources/search-hugging-face-datasets) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # List trainings (/es/api/trainings/list-trainings) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Autenticación (/es/authentication) Envía la clave como bearer token: ```http Authorization: Bearer ts_... ``` Una clave actúa como la cuenta que la creó: ve y gasta lo que esa cuenta ve y gasta. Crea y borra claves en [Configuración → Claves de API](https://typestrict.ai/es/settings#api-keys); borrar una clave la detiene al instante. ## Asistentes de IA [#asistentes-de-ia] Los asistentes conectados al [servidor MCP remoto](/es/agents) inician sesión con OAuth: inicias sesión en typestrict una vez y autorizas al asistente, y este recibe un token que actúa como tu cuenta. Para desconectar uno, quita el conector en el asistente. ## Mantenla en secreto [#mantenla-en-secreto] * Léela de una variable de entorno o de un gestor de secretos, nunca del código ni de un repositorio. * Llama a la API desde tus servidores. Una clave en el navegador o en una app es una clave que cualquiera copia. * Una clave por cada lugar que la usa, para que revocar una no detenga las demás. Las claves empiezan con `ts_`, para que los escáneres de secretos reconozcan una filtrada. ## Errores [#errores] Una clave ausente, desconocida, desactivada o vencida responde `401`: ```json { "error": "unauthorized", "message": "unauthorized" } ``` Todo error tiene la misma forma: un código `error` estable para decidir qué hacer y un `message` para personas. # Modelos base (/es/base-models) Tu modelo no se entrena desde cero: parte de un **modelo base**, un encoder que ya lee lenguaje y toma decisiones tipadas, y aprende tu decisión sobre él. Todo modelo base es nuestro, con el nombre `TS-{base}-{tamaño}`, abierto y aprobado para uso comercial (Apache-2.0). `GET /v1/encoders` los lista, con lo que se puede elegir ahora. | Modelo base | `encoder` | Tamaño | Idiomas | Contexto | Decision Index 0.3 | Entrenamiento | | ---------------------------------------------------------------------------------- | ----------------- | ------ | ------- | ------------ | ------------------ | ------------- | | [TS-moBERTo-150M](https://huggingface.co/typestrict/TS-moBERTo-150M) (recomendado) | `ts-moberto-150m` | 150M | EN, PT | 8,192 tokens | 31.20 / 33.89 | Disponible | | [TS-Ettin-150M](https://huggingface.co/typestrict/TS-Ettin-150M) | `ts-ettin-150m` | 150M | EN | 8,192 tokens | 31.96 / 34.78 | Disponible | | [TS-Ettin-68M](https://huggingface.co/typestrict/TS-Ettin-68M) | `ts-ettin-68m` | 68M | EN | 8,192 tokens | 27.61 / 30.46 | Disponible | | [TS-Ettin-32M](https://huggingface.co/typestrict/TS-Ettin-32M) | `ts-ettin-32m` | 32M | EN | 8,192 tokens | 19.70 / 22.45 | Disponible | | [TS-Ettin-17M](https://huggingface.co/typestrict/TS-Ettin-17M) | `ts-ettin-17m` | 17M | EN | 8,192 tokens | 15.76 / 18.52 | Disponible | El índice público del [Decision Index](https://github.com/apolinario/decision-index) 0.3, en la corrida de nuestro lab: el encoder solo, luego con los especialistas de código y de cálculo que vienen con los modelos publicados. Medido en benchmarks públicos, no en tu tarea: tu modelo se mide con tus ejemplos, contra Jev ([el cálculo de reembolso](/es/refund)). El contexto es cuánto texto cabe en un ejemplo; los ejemplos más largos se rechazan, nunca se cortan. ## TS-moBERTo-150M [#ts-moberto-150m] Nuestra base por defecto, en inglés y portugués, hecha para decisiones tipadas (`choice`, `noul`, `score`, con probabilidades y una confianza) en CPU. Parte de [moBERTo](https://huggingface.co/Tropic-AI/moBERTo-orig-tokenizer) (Apache-2.0) y se publicó antes como [Dinah-1](https://huggingface.co/Lukitaduarte/dinah-1), cuya corrida oficial del Decision Index marcó **34.32**, con los resultados en bruto publicados para auditoría. En decisiones tipadas reservadas para prueba (1,000 ítems cada una): 0.790 de exactitud en inglés y 0.780 en portugués. ## TS-Ettin [#ts-ettin] La misma receta sobre los [rerankers Ettin](https://huggingface.co/cross-encoder/ettin-reranker-150m-v1) (Apache-2.0), en cuatro tamaños, solo en inglés. El de 150M es la base más fuerte en el índice; los menores cambian puntos por velocidad y memoria, para teléfonos, navegadores y volúmenes altos. Su confianza todavía no está calibrada; tu modelo entrenado se sigue midiendo igual. ## Con qué se entrenaron [#con-qué-se-entrenaron] Los cinco siguen la misma receta, con los mismos datos, en dos etapas (2,048 tokens, luego 8,192) y el promedio de ambas. Cada fuente con la licencia que declara su propia ficha. Las fuentes bajo CC BY-SA y CDLA-Sharing se usan solo para entrenar y no se redistribuyen. | Área | Fuentes | | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Decisiones tipadas | ZefanCai/Open-Jev (CC0-1.0), LocalLLaMA/typed-decisions (Apache-2.0), typed-decisions-pt traducido con Qwen3-4B (Apache-2.0), tasksource/procedural-typed-decisions (Apache-2.0) | | Intenciones y atención al cliente | AmazonScience/massive (CC BY 4.0), Bitext customer support (CDLA-Sharing-1.0), BANKING77 (CC BY 4.0), CLINC150 (CC BY 3.0), FAQ_BACEN (Apache-2.0) | | Inferencia y verificación de hechos | WANLI (CC BY 4.0), SNLI (CC BY-SA 4.0), HoVer (CC BY-SA 4.0), FEVER-NLI (MIT; FEVER y Wikipedia CC BY-SA 3.0), ContractNLI (CC BY 4.0), bAbI-NLI (BSD), FaQuAD-NLI (CC BY 4.0), ExtraGLUE RTE y COPA en portugués (MIT) | | Razonamiento y conocimiento | CommonsenseQA (MIT), Cosmos QA (CC BY 4.0), BoolQ (CC BY-SA 3.0), HellaSwag (MIT), WinoGrande (Apache-2.0), split de entrenamiento de ARC (CC BY-SA 4.0), QASC (CC BY 4.0), StrategyQA (MIT), tareas de BIG-bench sin BBH (Apache-2.0), MMLU auxiliary train, partes ARC y OpenBookQA (MIT), GSM8K (MIT), CLadder (MIT) | | Salud, finanzas y derecho | PubMedQA (MIT), MedMCQA (Apache-2.0), twitter-financial-news-sentiment (MIT), financial-tweets-sentiment (MIT), NOSIBLE financial-sentiment (ODC-By), FinQA hallucination detection (MIT), pyRis/SEntFiN (MIT), CUAD (CC BY 4.0), jurisprudencias_br (CC BY 4.0), IBM Claim Stance (CC BY 3.0) | | Sentimiento, emoción y moderación | GoEmotions (Apache-2.0), Civil Comments (CC0-1.0), iSarcasmEval (MIT), B2W-Reviews01 (CC BY 4.0), multilingual-sentiments en portugués (Apache-2.0) | | Recuperación y alucinación | ESCI (Apache-2.0), HaluEval (Apache-2.0), RAGTruth (MIT), CNN/DailyMail (Apache-2.0), SQuAD 2.0 (CC BY-SA 4.0) | | Herramientas | glaive-function-calling-v2 (Apache-2.0), ToolACE (Apache-2.0), hermes-function-calling-v1 (Apache-2.0), nvidia/When2Call (CC BY 4.0) | | Phishing | LLMGen-Phishing-Email-Dataset (Apache-2.0), aura-phishing-email-corpus, parte SpamAssassin (CC BY 4.0) | | Ajedrez | Lichess puzzles (CC0-1.0), google-deepmind/searchless_chess (Apache-2.0) | | Humor | newyorker_caption_contest, tarea matching (CC BY 4.0) | | Hecho por nosotros | Traducciones de inglés a portugués con opus-mt-tc-big-en-pt (CC BY 4.0); correos de phishing sintéticos escritos con gpt-oss-120b, con etiquetas definidas por código (Apache-2.0); hogares sintéticos de electrodomésticos, ejemplos de alucinación en RAG y habilidades programáticas (aritmética, fechas, unidades, ordenamiento, grafos, salida de código), generados por nuestros scripts (MIT y Apache-2.0) | Los bloques de entrenamiento se cotejaron con las filas de prueba públicas del Decision Index (eliminación de duplicados exactos y casi duplicados, y solapamiento de 8-gramas en los bloques más recientes). ## Cuál elegir [#cuál-elegir] * **Si dudas, o en portugués:** TS-moBERTo-150M, el predeterminado. Es el más fuerte en nuestras decisiones tipadas reservadas para prueba (0.790 en inglés, 0.780 en portugués, contra 0.709 en inglés de TS-Ettin-150M). * **En inglés, y quieres comparar:** TS-Ettin-150M, el más alto en el Decision Index. Entrena los dos con los mismos datos y quédate con la versión que gane en tus ejemplos reservados. * **Cuando cada milisegundo o megabyte cuenta:** TS-Ettin-68M, 32M o 17M. Todo modelo base entrena igual y se mide con la misma regla, así que probar otro es una nueva versión del mismo entrenamiento. # Sacar el mejor modelo (/es/best-results) * **Tus propias categorías ganan.** El modelo supera a Jev con holgura en decisiones con las respuestas de tu empresa (tus colas, equipos, productos, intenciones): BANKING77 0.889 contra 0.797 de macro-F1, un conjunto de atención 0.998 contra 0.771. En preguntas genéricas con pocos datos (el tema de una noticia, el tipo de cláusula de un contrato con unos cientos de ejemplos) Jev ya sabe mucho y el margen es pequeño. Arma la decisión en torno a tus respuestas. * **Los ejemplos por respuesta importan más que el total.** Apunta a cientos de ejemplos etiquetados por respuesta cuando los tengas. Nuestros modelos base están preentrenados en decisiones, lo que ayuda más con muy pocos ejemplos; con muchos, deciden tus datos. * **La respuesta más débil marca el nivel.** Un modelo es tan bueno como su peor respuesta: una respuesta con pocos ejemplos arrastra a todo el modelo. Une respuestas raras y parecidas, o junta más ejemplos de ellas, antes de entrenar. * **Respuestas que no se superponen, con descripción.** La descripción de cada respuesta es parte de lo que lee el modelo. Escríbelas para que una persona nunca dude entre dos. * **La entrada de producción.** Entrena con el texto que existe al momento de la decisión, nada que solo se sabe después (un campo "resuelto por" cuando la pregunta es qué equipo lo resuelve). * **Etiquetas consistentes.** Al etiquetar los ejemplos de prueba, el mismo caso recibe siempre la misma respuesta: el modelo se mide contra esas respuestas. ## Antes de enviar [#antes-de-enviar] Envía una tabla limpia (CSV o JSON lines), no la exportación en bruto. Tu asistente de IA puede hacerlo por ti con las [skills](/es/agents): 1. **Una fila por ejemplo**, con una columna de texto con todo aquello en que se basa la decisión (asunto y cuerpo, o los campos que leería una persona) y nada más. 2. **Una forma de escribir cada respuesta**: `Billing`, `billing ` y `Faturamento` son una sola respuesta. Deja fuera las filas vacías. 3. **Respuestas raras resueltas ahora**: unidas con la respuesta más cercana, o con más ejemplos. 4. **Sin fugas**: columnas o texto que solo existen después de la decisión. 5. **Sin duplicados exactos**, y ningún ejemplo con más de unos 30.000 caracteres (se rechazan, nunca se cortan). 6. **Un objetivo preciso**: la pregunta y una línea por respuesta sobre cuándo aplica. Cuanto más preciso, mejor la primera propuesta. ## Revisar la propuesta [#revisar-la-propuesta] En cuanto la propuesta está lista, antes de etiquetar, revísala (la pantalla de Revisión, `typestrict review`, o `structure.stats` en la API) y envía lo que haya que cambiar como feedback: 1. **Ejemplos por respuesta.** Cientos por respuesta es donde el modelo se vuelve bueno, y una respuesta necesita al menos 5 ejemplos de prueba para medirse. Los ejemplos de prueba son el 20% de tus datos (hasta 2.000) cuando traen respuesta, o 150 al azar que tú etiquetas cuando no: entonces una respuesta con menos de un 3% de los datos recibe menos de 5. Une una respuesta rara con la más cercana, o agrega ejemplos de ella. 2. **Respuestas que se superponen.** Lee los ejemplos de cada respuesta. Si una persona intercambiaría dos respuestas, únelas o reescribe sus descripciones hasta que el límite quede claro. Cuando los datos no traían respuesta, poco acuerdo entre los preetiquetadores señala el mismo problema. 3. **Etiquetas que parecen erróneas.** Un ejemplo cuya respuesta no coincide con su texto indica una columna de respuesta ruidosa: corrige de dónde viene la respuesta. 4. **Cada aviso.** Cada uno dice qué cambiar. 5. **Duplicados y fugas.** El texto debe ser lo que existe al momento de la decisión. 6. **La pregunta.** Decide con las respuestas de tu empresa. Los modelos grandes ya responden bien preguntas genéricas (tema, sentimiento); tus colas, equipos y productos son lo que solo tus datos saben. ## Cuando no supera a Jev [#cuando-no-supera-a-jev] La comparación dice por qué (`model.jev.superiority.reason`): una ganancia demasiado pequeña para estar seguros, o una respuesta que queda detrás de Jev. Más ejemplos de las respuestas débiles, u otro [modelo base](/es/base-models) con los mismos datos, son los próximos intentos. Cada versión se mide con los mismos ejemplos reservados, así que las versiones se comparan de forma justa. ## En producción [#en-producción] Usa la `confidence` del modelo para decidir qué automatizar y qué enviar a una persona. El resultado muestra exactamente eso, la exactitud en el 80% de respuestas más confiadas: empieza automatizando por encima de un umbral y ajústalo con lo que veas. Hazle al modelo la pregunta y las opciones con que se entrenó, como están en `decision_ai.json`. # CLI (/es/cli) Un binario para macOS, Linux y Windows que hace lo que hace el panel. Código abierto: [typestrict-lab/cli](https://github.com/typestrict-lab/cli). ```bash curl -fsSL https://typestrict.ai/install.sh | sh # macOS y Linux; Windows: el zip de la última release typestrict login # pega una clave de API, o define TYPESTRICT_API_KEY ``` ## El flujo [#el-flujo] ```bash typestrict train tickets.csv --goal "¿Qué equipo atiende el ticket?" --watch # sube, enmascara, lee typestrict structure # la agente convierte los datos en ejemplos de entrenamiento typestrict review # su propuesta: la pregunta, las respuestas, los avisos typestrict structure --feedback "..." # ajústala typestrict label # cuando se pida, responde los ejemplos de prueba en la terminal typestrict run --watch # muestra el costo y pregunta antes de gastar el crédito typestrict result # el veredicto contra Jev typestrict pull # decision_ai.json, tokenizer.json, onnx/model_8bit.onnx ``` | Comando | Qué hace | | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | | `train [--goal] [--question] [--hf org/nombre:archivo] [--github org/nombre] [--no-anonymize] [--watch]` | Envía los datos y empieza a preparar un entrenamiento. | | `status [] [--watch]` | Todos los entrenamientos con su paso y próxima acción, o uno de ellos. `--watch` lo sigue y sale con 1 si falla. | | `structure [--question] [--feedback]` | Ejecuta la agente de estructuración, o de nuevo con las decisiones elegidas o tu feedback. | | `suggest ` | Pide a la agente decisiones que estos datos enseñan. | | `review ` | Muestra la propuesta de la agente. | | `label ` | Responde los ejemplos de prueba uno a uno. | | `encoders` | Los modelos base y cuáles se pueden elegir. | | `credits` | Tu saldo. | | `run [--base ts-moberto-150m] [--yes] [--watch]` | Empieza el entrenamiento. Pregunta antes de gastar, salvo con `--yes`. | | `result ` | El veredicto contra Jev y hasta cuándo se pueden descargar los archivos. | | `pull [--dir]` | Descarga el paquete del modelo. | | `mcp` | El servidor MCP por stdio, para asistentes. | Todo comando acepta `--json` para salida legible por máquina, y encaja en scripts y CI. ## Para asistentes [#para-asistentes] ```bash typestrict mcp ``` El mismo flujo como herramientas MCP: `list_trainings`, `get_training`, `wait_for_change`, `create_dataset`, `structure_dataset`, `suggest_decisions`, `next_example_to_label`, `label_example`, `list_base_models`, `get_credits`, `quote_training`, `start_training`, `get_model`, `get_audit`, `download_model`. Empezar un entrenamiento siempre pasa por una cotización y su confirmación, así que un asistente nunca gasta un crédito sin preguntar. Las mismas herramientas se sirven de forma remota en `https://api.typestrict.ai/mcp`, sin nada que instalar. El servidor local es para cuando el asistente debe enviar archivos de cualquier tipo desde tu disco y guardar el modelo en tu proyecto. La configuración de cada asistente: [Asistentes de IA](/es/agents). # Ejecútalo donde quieras (/es/deploy) El contenedor está en construcción; hoy un modelo se descarga como ONNX, pesos y paquete. Esta página es su especificación. El runtime de servicio es open source (Apache-2.0). Cada modelo también se entrega como imagen de contenedor: el modelo, un runtime de CPU (ONNX Runtime) y un servidor HTTP, sin nada que configurar. Habla la misma API de decisión que Jev, así que pasar de Jev a tu propio modelo es cambiar una URL base. | Endpoint | Qué hace | | -------------------- | --------------------------------------------------------------------------------- | | `POST /v1/systemone` | Responde preguntas sobre un texto, en el formato de solicitud y respuesta de Jev. | | `GET /v1/models` | El modelo que contiene, por nombre. | | `GET /healthz` | `ok` cuando está listo, para health checks. | | Variable | Por defecto | Qué hace | | ------------------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `PORT` | `8080` | El puerto en el que escucha (Cloud Run y Lambda lo definen). | | `TYPESTRICT_TOKEN` | ninguno | Si está definida, cada solicitud debe llevar `Authorization: Bearer `. Prefiere la autenticación propia de tu plataforma (Cloud Run IAM, Lambda IAM) cuando la tengas. | Sin GPU, sin acceso a internet y sin llamadas a nosotros: las solicitudes y los datos se quedan en tu infraestructura. ## Docker [#docker] ```bash typestrict pull --container # o: docker load -i .tar (enlace de descarga en la página del modelo) docker run -p 8080:8080 typestrict/ ``` ```bash curl http://localhost:8080/v1/systemone -H "Content-Type: application/json" -d '{ "model": "ticket-router", "state": "Me cobraron dos veces. Por favor, ayúdenme.", "questions": { "team": { "type": "choice", "instructions": "¿Qué equipo atiende el ticket?", "criteria": { "billing": "Pagos y facturas", "support": "Todo lo demás" } } } }' # una respuesta se ve así: # { "model": "ticket-router", "answers": { "team": { "type": "choice", "choice": "billing", "confidence": 0.97, # "probabilities": { "billing": 0.97, "support": 0.03 } } }, "usage": { "input_tokens": 41, "output_tokens": 0 } } ``` ## Google Cloud Run [#google-cloud-run] Cloud Run ejecuta imágenes de Artifact Registry. Copia la imagen allí y luego despliega: ```bash typestrict pull --to us-docker.pkg.dev///ticket-router gcloud run deploy ticket-router \ --image us-docker.pkg.dev///ticket-router \ --region us-central1 --cpu 1 --memory 1Gi \ --no-allow-unauthenticated ``` `--no-allow-unauthenticated` lo mantiene privado: quienes llaman necesitan un token de identidad de una cuenta de servicio con el rol `roles/run.invoker`. Define `--min-instances 1` si la primera solicitud después de un periodo sin tráfico debe ser rápida. ## AWS Lambda [#aws-lambda] La imagen incluye el [AWS Lambda Web Adapter](https://github.com/awslabs/aws-lambda-web-adapter), así que la misma imagen corre en Lambda sin cambios. Lambda ejecuta imágenes de ECR en la misma cuenta y región: ```bash typestrict pull --to .dkr.ecr.us-east-1.amazonaws.com/ticket-router aws lambda create-function --function-name ticket-router \ --package-type Image \ --code ImageUri=.dkr.ecr.us-east-1.amazonaws.com/ticket-router:latest \ --role arn:aws:iam:::role/ \ --memory-size 2048 --timeout 30 aws lambda create-function-url-config --function-name ticket-router --auth-type AWS_IAM ``` En Lambda, la CPU crece con la memoria: 2 GB es un buen punto de partida. La primera solicitud después de un arranque en frío carga el modelo. ## Firebase [#firebase] Firebase Functions no ejecuta imágenes propias, así que el modelo corre en Cloud Run (arriba) y Firebase llega hasta él: * **Hosting:** dirige una ruta directo al servicio de Cloud Run con un rewrite en `firebase.json`: ```json { "hosting": { "rewrites": [{ "source": "/api/decide", "run": { "serviceId": "ticket-router", "region": "us-central1" } }] } } ``` * **Functions:** llama al servicio de Cloud Run desde tu función con un token de identidad, como a cualquier otra API HTTP. ## Kubernetes [#kubernetes] ```yaml apiVersion: apps/v1 kind: Deployment metadata: { name: ticket-router } spec: replicas: 2 selector: { matchLabels: { app: ticket-router } } template: metadata: { labels: { app: ticket-router } } spec: containers: - name: model image: /ticket-router ports: [{ containerPort: 8080 }] resources: { requests: { cpu: "1", memory: 1Gi }, limits: { memory: 2Gi } } readinessProbe: { httpGet: { path: /healthz, port: 8080 } } livenessProbe: { httpGet: { path: /healthz, port: 8080 }, periodSeconds: 30 } --- apiVersion: v1 kind: Service metadata: { name: ticket-router } spec: selector: { app: ticket-router } ports: [{ port: 80, targetPort: 8080 }] ``` El modelo no guarda estado, así que escala horizontalmente con réplicas (o con un HorizontalPodAutoscaler por CPU). # Glosario (/es/glossary) **Exactitud (accuracy).** La proporción de respuestas correctas. Simple, pero esconde las respuestas raras: un modelo que siempre da la respuesta más común puede sacar una nota alta. **Anonimización (enmascaramiento).** Reemplazar los datos personales de tus archivos (nombres, correos, teléfonos, documentos, números de tarjeta) por marcadores como `[EMAIL]`, antes de que cualquier otra cosa los lea. **Clave de API.** Un secreto que permite que tu código llame a la API como tu cuenta. Las nuestras empiezan con `ts_`. **Modelo base (encoder).** El modelo del que parte tu modelo. Ya lee lenguaje; el entrenamiento le enseña tu decisión. Ver [Modelos base](/es/base-models). **Bootstrap.** Medir de nuevo sobre muchos remuestreos de los mismos ejemplos de prueba, para ver cuánto podría moverse un resultado por azar. El [cálculo de reembolso](/es/refund) usa 2,000. **Brier score y Brier skill.** Qué tan lejos están las probabilidades de lo que pasó. Brier skill lo convierte en una puntuación de 0 a 1 donde más alto es mejor: un modelo que dice 90% y acierta suma más que uno que dice 51% y acierta. **Calibración.** Si "80% seguro" acierta cerca del 80% de las veces. En un modelo calibrado se puede confiar en la confianza para decidir qué automatizar. **Confianza.** Qué tan seguro está el modelo de la respuesta que eligió, de 0 a 1. **Contexto.** Cuánto texto cabe en un ejemplo, en tokens (pedazos de palabras). Depende del modelo base. **Crédito.** Lo que cuesta un entrenamiento. Vuelve si el modelo no supera a Jev o si el entrenamiento falla. **API de decisión.** Una API que responde preguntas sobre un texto con un resultado tipado en lugar de texto libre: una `choice` entre opciones, un `noul` (verdadero o falso, como probabilidad) o un `score` en una escala, cada uno con probabilidades. La API de Jev, que también habla el contenedor de tu modelo, es una de ellas. **Encoder.** Un modelo que lee un texto y lo representa, sin escribir texto. Pequeño, rápido y barato de correr en una CPU, por eso sirve para decisiones. **Ejemplos reservados (de prueba).** Ejemplos apartados antes del entrenamiento que el modelo nunca ve, para que la medición sea honesta. **Jev.** El modelo de referencia del mercado para decisiones, un modelo general grande. Comparamos cada modelo contra él con tus propios ejemplos. **Macro-F1.** El F1 (un equilibrio entre precisión y exhaustividad) de cada respuesta, promediado con todas las respuestas pesando igual. Las respuestas raras cuentan tanto como las comunes. **Modelo multitarea.** Un solo modelo que toma varias decisiones sobre la misma entrada. Se mide por tarea contra su modelo base. **ONNX.** Un formato de archivo abierto para modelos. Corre en CPUs en cualquier lenguaje con ONNX Runtime, en servidores, navegadores y teléfonos. **Cuantización (8 bits).** Guardar los números del modelo con menos bits. Más pequeño y más rápido, con una pérdida mínima. **Exactitud selectiva.** La exactitud sobre solo las respuestas más seguras (el 80% de ellas en la garantía): lo que obtienes al automatizar esas y enviar el resto a una persona. **Agente de estructuración.** Nuestra agente que lee tus datos enmascarados y los convierte en ejemplos de entrenamiento para la decisión que quieres. **F1 de la peor clase.** El F1 de la respuesta que el modelo maneja peor. Evita que un promedio esconda una respuesta que colapsó. # Introducción (/es) typestrict entrena un modelo de decisión pequeño con tus datos: lee un ticket, un mensaje o un documento y responde con una decisión estructurada y tipada (una etiqueta, un sí o no, una puntuación), con el mismo formato de respuesta que Jev, el modelo de referencia del mercado. Si tu modelo no supera a Jev en ejemplos que nunca vio en el entrenamiento, el crédito vuelve. ## Cómo va un entrenamiento [#cómo-va-un-entrenamiento] Todo entrenamiento pasa por cinco pasos, igual en el panel, la API y los asistentes: 1. **Datos**: envías archivos, conectas Google Drive u OneDrive, o partes de un dataset público. Los datos personales se enmascaran antes de cualquier otra lectura. 2. **Revisión**: nuestra agente organiza los datos en ejemplos de entrenamiento. Revisas la propuesta y la ajustas. 3. **Modelo base**: eliges el modelo sobre el que entrenar, aprobado para uso comercial, y confirmas el costo. 4. **Entrenamiento**: lo entrenamos y lo medimos contra Jev. 5. **Resultado**: descargas el modelo (ONNX y pesos) y lo usas donde quieras, sin GPU. ## Por dónde empezar [#por-dónde-empezar] # Límites (/es/limits) | Límite | Valor | | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | | Tamaño de un archivo | 200 MB | | Archivos en un dataset | 500 | | Fuentes públicas (Hugging Face, GitHub) en un dataset | 10 | | Decisiones construidas a partir de un dataset | 12 | | Longitud de la pregunta de una decisión | 500 caracteres | | Longitud de un ajuste a la agente | 1,000 caracteres | | Texto de un ejemplo | El contexto del modelo base (ver [Modelos base](/es/base-models)); los ejemplos más largos se rechazan, nunca se recortan | | Ejemplos de prueba medidos contra Jev | 20% de los ejemplos etiquetados, hasta 2,000 | | URL de subida | Válida por 15 minutos | | Enlaces de descarga y de auditoría | Válidos por 15 minutos; pide uno nuevo cuando quieras mientras se guarden los archivos | | Página de una lista | 25 por defecto, hasta 100 | | Costo de un entrenamiento | 1 crédito, devuelto si el modelo no supera a Jev o si el entrenamiento falla | Las imágenes no se usan en esta versión: aparecen como **No usados**, con el motivo. # Inicio rápido (/es/quickstart) ## 1. Crea una clave de API [#1-crea-una-clave-de-api] Abre [Configuración → Claves de API](https://typestrict.ai/es/settings#api-keys) y crea una clave. Empieza con `ts_` y se muestra una sola vez: guárdala en un gestor de secretos o en una variable de entorno. ```bash export TYPESTRICT_API_KEY=ts_... ``` Compruébala: curl TypeScript Python ```bash curl https://api.typestrict.ai/v1/credits \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" ``` ```ts const res = await fetch("https://api.typestrict.ai/v1/credits", { headers: { Authorization: `Bearer ${process.env.TYPESTRICT_API_KEY}` }, }) console.log(await res.json()) // { balance: 1, per_model: 1 } ``` ```python import os, requests res = requests.get( "https://api.typestrict.ai/v1/credits", headers={"Authorization": f"Bearer {os.environ['TYPESTRICT_API_KEY']}"}, ) print(res.json()) # {'balance': 1, 'per_model': 1} ``` ## 2. Envía tus datos [#2-envía-tus-datos] Describe los archivos y la decisión que quieres. La respuesta trae una URL de subida por archivo, válida por 15 minutos. ```bash curl https://api.typestrict.ai/v1/datasets \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "tickets de soporte", "goal": "¿Qué equipo atiende el ticket?", "files": [{ "filename": "tickets.csv", "content_type": "text/csv", "size": 48213 }] }' # { "id": "", "uploads": [{ "file_id": "", "filename": "tickets.csv", "url": "https://..." }] } ``` Sube cada archivo a su URL y confírmalo: ```bash curl -X PUT --upload-file tickets.csv "" curl -X POST https://api.typestrict.ai/v1/datasets//files//complete \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" ``` ## 3. Sigue el entrenamiento [#3-sigue-el-entrenamiento] Cada entrenamiento dice en qué paso está y qué necesita a continuación: ```bash curl https://api.typestrict.ai/v1/trainings \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" # { "data": [{ "kind": "dataset", "id": "", "step": 1, "next_action": "wait", ... }], "next": null } ``` Mientras `next_action` sea `wait`, estamos leyendo y enmascarando los datos. Después la agente los estructura y el entrenamiento sigue: [Entrenamientos](/es/trainings) lista cada próxima acción y la llamada que la responde. # Cálculo de reembolso (/es/refund) Todo modelo entrenado en una decisión se mide contra Jev, el modelo de referencia del mercado, con tus propios ejemplos. Si no supera a Jev, el crédito vuelve solo a tu saldo. "Superar" no es "una métrica por cualquier margen": el cálculo de reembolso exige una ganancia que se sostenga al remuestrear y ninguna métrica que colapse. ## Los ejemplos de prueba [#los-ejemplos-de-prueba] Antes del entrenamiento, apartamos ejemplos que el modelo nunca ve: * **El 20% de tus ejemplos etiquetados**, sorteados por respuesta para que cada respuesta mantenga su proporción, **hasta 2,000**. * Cuando tus datos no tienen respuestas, en su lugar los ejemplos que una persona etiquetó en el paso de revisión. El sorteo usa como semilla el dataset, así que cada versión de un modelo se mide con los mismos ejemplos. Jev responde los mismos ejemplos con la misma pregunta: sus respuestas se usan solo para medir, nunca para entrenar. ## Cuatro métricas [#cuatro-métricas] Cada sistema recibe cuatro puntuaciones en los ejemplos de prueba, todas mejores cuanto más altas: | Métrica | Qué dice | | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- | | `macro_f1` | Con qué frecuencia la respuesta es correcta, con todas las respuestas pesando igual, así que una respuesta rara cuenta tanto como una común. | | `brier_skill` | Qué tan buenas son las probabilidades: `1 - mean Brier / 2`, de 0 a 1. Premia estar seguro cuando acierta y dudar cuando se equivoca. | | `selective_acc_80` | La exactitud sobre el 80% de respuestas más seguras: lo que obtienes al automatizar las seguras y enviar el resto a una persona. | | `worst_class_f1` | El F1 de la respuesta más débil con 5 ejemplos o más. Ninguna respuesta puede colapsar. | ## La regla [#la-regla] La ganancia ponderada sobre Jev es ```text G = 0.5 × Δmacro_f1 + 0.3 × Δbrier_skill + 0.2 × Δselective_acc_80 ``` donde `Δ` es nuestra puntuación menos la de Jev. El modelo **supera a Jev** solo si se cumplen las dos condiciones: 1. **La ganancia es real.** Remuestreamos los ejemplos de prueba 2,000 veces (un bootstrap pareado: el mismo sorteo para ambos sistemas) y recalculamos `G` cada vez. El percentil 5 de esos 2,000 valores debe estar por encima de cero: `G > 0` con 95% de confianza. 2. **Nada colapsa.** Ninguna métrica puede quedar por debajo de la de Jev por más de su margen: 0.02 para las tres primeras, 0.05 para `worst_class_f1`. Cualquier otro resultado es un reembolso, empates incluidos. Cuando las probabilidades empatan en el primer lugar, ambos sistemas reciben el mismo beneficio de la duda: la respuesta cuenta como correcta si la correcta está entre las empatadas. La semilla del bootstrap sale del SHA-256 de los textos de los ejemplos de prueba. Mismos ejemplos, mismas respuestas, mismos números, siempre. ## Verifícalo tú mismo [#verifícalo-tú-mismo] Cada modelo tiene un archivo de auditoría (`GET /v1/models/{id}/audit`): para cada ejemplo de prueba, el SHA-256 de su texto, la respuesta correcta y las probabilidades de ambos sistemas, además del informe con todos los números de arriba. El verificador reconstruye el informe completo con la biblioteca estándar de Python y falla si algún número difiere: ```bash curl -O https://typestrict.ai/verify_audit.py python3 verify_audit.py audit.json ``` La auditoría no guarda ningún texto tuyo, solo hashes y probabilidades, así que se queda con el registro del modelo incluso después de que sus archivos expiran (ver [Retención](/es/retention)). ## Cuándo no aplica la garantía [#cuándo-no-aplica-la-garantía] * **Varias decisiones en un modelo** (un plan multitarea): cada tarea se mide contra el modelo base del que partió, no contra Jev, y no hay reembolso por el resultado. * **Un entrenamiento que falla** también devuelve el crédito, sea cual sea el tipo de modelo. # Retención (/es/retention) El registro de cada dataset y modelo se mantiene: su nombre, sus números, el veredicto contra Jev y la [auditoría](/es/refund#verifícalo-tú-mismo) de ese veredicto. Lo que se puede descargar o usar para entrenar se guarda por un tiempo limitado. | Qué | Cuánto tiempo | Después | | -------------------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Archivo original subido | Hasta que se enmascara | Se borra justo después del enmascaramiento. Solo se usa la copia enmascarada. | | Los archivos de un modelo (ONNX, pesos, paquete, ejemplos de prueba) | 30 días después de terminar el entrenamiento | Se borran. El registro y la auditoría se mantienen. | | Un modelo que no superó a Jev | De inmediato | Sus archivos se borran cuando sale el veredicto: el crédito volvió, no hay nada que entregar. | | Un modelo publicado | Hasta que está en tu Hugging Face | Sus archivos salen de nuestro almacenamiento; tu repositorio es donde vive y desde donde se descarga. | | Los datos de un dataset | 90 días después de su último uso | Se borran, incluidas las copias que guardamos de vistas previas y muestras. Iniciar un entrenamiento con ellos, o copiarlos para ajustar, cuenta como uso y suma 90 días. | | Una subida que nunca terminó, o que falló | 30 días | Se borra junto con su registro. | | Una cuenta cerrada | 30 días después de que lo pidas | Se borra todo. Hasta entonces puedes cancelar, y tus claves de API se detienen al instante. | El panel muestra las fechas: **Disponible hasta** en Modelos y Datos. La API las devuelve en cada modelo (`files_expire_at`, y `files_deleted_at` una vez borrados) y dataset (`data_expire_at`, `data_deleted_at`). ## Después del vencimiento [#después-del-vencimiento] * Descargar un modelo vencido responde `410` con `"error": "expired"`. Su página, métricas y auditoría se mantienen. * Los datos vencidos no pueden iniciar un entrenamiento, ni estructurarse, etiquetarse o copiarse (`410`). Para entrenar de nuevo, súbelos otra vez. * Descarga tu modelo dentro de los 30 días posteriores a su entrenamiento, o publícalo en tu Hugging Face desde su página. Los registros de pago se guardan por 5 años y los registros de acceso por 6 meses, como exige la ley brasileña. # Seguridad y privacidad (/es/security) ## Tus archivos [#tus-archivos] * **Primero el enmascaramiento.** Antes de que cualquier otra cosa lea tus datos, enmascaramos los datos personales: nombres, correos, teléfonos, documentos como CPF y CNPJ, y números de tarjeta. El archivo original subido se borra en cuanto existe la copia enmascarada. * **La agente ve muestras, no archivos.** La agente de estructuración (un modelo de lenguaje al que se accede por OpenRouter) ve la forma de tus datos y muestras enmascaradas, nunca los archivos sin procesar. * **Las máquinas de entrenamiento son temporales.** El entrenamiento corre en GPUs alquiladas en vast.ai. Reciben solo datos enmascarados, y cada máquina se destruye cuando termina la ejecución. * **Jev solo mide.** La comparación envía los ejemplos de prueba enmascarados a Jev por OpenRouter. Sus respuestas se usan para medir, nunca para entrenar. * **Tu decisión de omitir el enmascaramiento.** Si declaras que tus archivos no contienen datos personales, el enmascaramiento se omite, a tu pedido y bajo tu responsabilidad. ## Tu modelo [#tu-modelo] Después del entrenamiento, el modelo corre donde lo pongas: en tus servidores, tu nube, el navegador o un teléfono. Lo que le preguntes nunca vuelve a nosotros. Es un archivo, no un servicio del que dependas. ## Tu cuenta [#tu-cuenta] * Las contraseñas se guardan solo como hash; también puedes entrar con una passkey, Google o Hugging Face. * Las claves de API se guardan solo como hash SHA-256 y se muestran una sola vez. Empiezan con `ts_`, para que los escáneres de secretos reconozcan una filtrada. * Los asistentes de IA en el servidor MCP remoto solo obtienen acceso después de que entras y los permites (OAuth con PKCE); sus tokens valen solo para ese servidor y vencen en menos de una hora, renovados mientras dure la conexión. * Cada llamada se verifica contra el dueño: una cuenta nunca lee los datasets ni los modelos de otra. ## Cuánto tiempo guardamos las cosas [#cuánto-tiempo-guardamos-las-cosas] Ver [Retención](/es/retention). La [política de privacidad](https://typestrict.ai/es/privacy) es la versión completa y vinculante de esta página, con la lista de proveedores que procesan datos para nosotros. # Entrenamientos (/es/trainings) Un entrenamiento es un dataset en preparación (pasos 1 a 3) o, una vez que corre, un modelo (pasos 4 y 5). Cada uno trae `step` (1 a 5) y `next_action`, los mismos dos campos que leen el panel, la CLI y los asistentes, para que cualquiera de ellos conduzca el flujo. ```json { "kind": "dataset", "id": "0199f0c4-…", "name": "tickets de soporte", "status": "ready", "step": 2, "next_action": "structure" } ``` ## Próximas acciones [#próximas-acciones] | `next_action` | Qué significa | Qué llamar | | ---------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | | `upload_files` | Faltan archivos. | `PUT` de cada archivo en su URL, luego `POST /v1/datasets/{id}/files/{archivo}/complete` | | `wait` | Estamos trabajando en él. | Léelo de nuevo en unos segundos: `GET /v1/datasets/{id}` o `GET /v1/models/{id}` | | `start_over` | No pudimos leer los datos. | Crea un dataset nuevo con los archivos corregidos | | `structure` | Los datos se leyeron y enmascararon. | `POST /v1/datasets/{id}/structure`, o `POST /v1/datasets/{id}/suggest` para ver decisiones antes | | `pick_decisions` | La agente sugirió decisiones. | `POST /v1/datasets/{id}/structure` con `{ "questions": [...] }` | | `label_examples` | Los ejemplos reservados para la prueba necesitan respuesta. | `GET /v1/datasets/{id}/labels/next`, luego `POST /v1/datasets/{id}/labels/{tarea}` con `{ "label": "..." }` | | `start_training` | Listo para entrenar. | `GET /v1/encoders`, luego `POST /v1/datasets/{id}/models` con `{ "encoder": "ts-moberto-150m" }` (1 crédito) | | `retry` | El entrenamiento falló y el crédito volvió. | `POST /v1/datasets/{dataset}/models` de nuevo | | `download` | El modelo está listo. | `GET /v1/models/{id}/download` devuelve un enlace válido por 15 minutos, hasta `files_expire_at` | | `none` | Los archivos del modelo salieron (expiraron, reembolso o en tu Hugging Face). | Nada: el registro y la auditoría se mantienen ([Retención](/es/retention)) | | `expired` | Los datos del dataset expiraron. | Súbelos de nuevo para entrenar ([Retención](/es/retention)) | Iniciar un entrenamiento sin créditos responde `402` con `"error": "no_credits"`. ## Páginas [#páginas] Las listas llegan de la más nueva a la más antigua, una página a la vez: ```json { "data": [ ... ], "next": "6b3f…" } ``` Pasa `limit` (de 1 a 100, 25 por defecto) y, para la página siguiente, `cursor` con el último `next`. Una página sigue igual mientras llegan entrenamientos nuevos arriba. `GET /v1/models` y `GET /v1/datasets` también aceptan `status` (`done` para modelos terminados, `ready` para datasets estructurados). ```bash curl "https://api.typestrict.ai/v1/models?status=done&limit=10" \ -H "Authorization: Bearer $TYPESTRICT_API_KEY" ```