---
title: Laya Provider Guide
description: An open-weights decision provider — typed, calibrated judgments from Convai Innovations' Laya, at any Laya server or LiteLLM proxy route you configure
keywords: laya, decide, decision model, open weights, litellm, calibrated confidence, system one
---
# Laya Provider Guide
**A provider of `decide`** — the same typed `boolean` / `choice` / `score`
answers as [TypeSafe's Jev](typesafe.md), from an open-weights model you can
run yourself. It emits no text at all.
---
## Overview
Laya is Convai Innovations' Apache-2.0 "System One" decision model. You send
one `state` plus named, typed questions; an encoder answers every question in a
single forward pass and returns a probability distribution for each. NeuroLink
calls whatever base URL you configure — a Laya server, or a LiteLLM proxy with a
pass-through route to one. There is no built-in endpoint.
### Key Facts
| | |
| --------------------- | ------------------------------------------------------------------------------------------------- |
| Inference type | `decide` only |
| Checkpoints | `typed-decisions` (default, fine-tuned for typed decisions), `multilingual`, `english`, or `auto` |
| Input window | 1,024 tokens (`typed-decisions`, `multilingual`); 512 (`english`) |
| Questions per request | up to 64 |
| Endpoint | `/predict`; the base URL is required, with no default |
| Precedence | used automatically when its key and base URL are set and no TypeSafe key is |
---
## Quick Start
### 1. Get an endpoint and a key
Run a Laya server (see [below](#running-your-own-laya-server)), or use a LiteLLM
proxy with a pass-through route to one. On LiteLLM, create a virtual key and add
the route's `/predict` path (and `/health`, if you want to probe it) to the
key's **Allowed Routes**; a key without them is refused with a 403
`Key/team not allowed to access passthrough route`.
### 2. Configure
Both the base URL and the key are required. Set them in the environment:
```bash
export LAYA_BASE_URL=https://your-proxy.example.com/laya # NeuroLink calls /predict
export LAYA_API_KEY=sk-... # the key your endpoint accepts
export LAYA_MODEL=typed-decisions # optional
```
or in the config passed to the SDK, exactly as for any other provider. Values
passed per call override the constructor's, which override the environment:
```typescript
const neurolink = new NeuroLink({
credentials: {
laya: {
baseURL: "https://your-proxy.example.com/laya",
apiKey: process.env.MY_LAYA_KEY,
},
},
});
```
### 3. Use it
```typescript
import { NeuroLink, readDecisionChoice } from "@juspay/neurolink";
const neurolink = new NeuroLink();
const result = await neurolink.decide({
provider: "laya",
state: "We were billed twice for March. Please refund it today.",
questions: {
team: {
type: "choice",
instructions: "Which team should handle this?",
criteria: {
billing: "Payments and refunds",
technical: "Bugs",
sales: "Pricing",
},
},
urgent: { type: "boolean", instructions: "Is this urgent?" },
},
});
const team = readDecisionChoice(result.answers, "team");
```
### From the CLI
```bash
neurolink decide "We were billed twice for March." --provider laya \
--questions '{"urgent":{"type":"boolean","instructions":"Is this urgent?"}}'
```
---
## When NeuroLink uses it
Every built-in consumer of `decide` — model routing, relevance-driven
compaction, tool routing and RAG planning — asks for the default decision
provider. That is the first one that is configured — in the environment or in
the `credentials` passed to the SDK — in the order TypeSafe, Laya,
[XOR](xor.md), [SubQ](subq.md), [Perplexity](perplexity-decider.md),
[Cloudflare Clef](cloudflare-clef.md),
[OpenAI Decisions](openai-decisions.md), then [ScaleDown](scaledown.md). TypeSafe has two keys,
`TYPESAFE_API_KEY` and `AI_GATEWAY_API_KEY` (its Vercel AI Gateway route), and
either one counts. Laya counts only with both its key and its base URL, and so
does XOR. SubQ counts with its key alone, `SUBQ_API_KEY`. Perplexity counts with
its key alone, and that key,
`PERPLEXITY_API_KEY`, is shared with Perplexity's text provider. Cloudflare Clef
counts only with both `CLOUDFLARE_API_KEY` and `CLOUDFLARE_ACCOUNT_ID`, the same
two variables the Workers AI text provider reads. OpenAI Decisions counts with its
key alone, `OPENAI_API_KEY`, which the OpenAI chat provider reads too.
ScaleDown counts with its key alone, `SCALEDOWN_API_KEY`, which no other provider
reads. So:
- **A TypeSafe key, plus Laya's key and base URL:** built-in features use
TypeSafe; Laya runs only where a caller asks for `provider: "laya"`.
- **Only Laya's key and base URL:** built-in features use Laya.
- **Laya's key and base URL, plus XOR's:** built-in features use Laya; XOR runs
only where a caller asks for `provider: "xor"`.
- **A Laya key with no base URL:** Laya is not configured. Built-in features
ignore it, and `provider: "laya"` fails with `Laya requires a base URL`.
- **Laya's key and base URL, plus a Perplexity key:** built-in features use
Laya; Perplexity runs only where a caller asks for
`provider: "perplexity-decider"`.
- **Laya's key and base URL, plus `CLOUDFLARE_API_KEY` and
`CLOUDFLARE_ACCOUNT_ID`:** built-in features use Laya; Cloudflare Clef runs
only where a caller asks for `provider: "cloudflare-clef"`.
- **Laya's key and base URL, plus `SUBQ_API_KEY`:** built-in features use Laya;
SubQ runs only where a caller asks for `provider: "subq"`.
- **Laya's key and base URL, plus `SCALEDOWN_API_KEY`:** built-in features use
Laya; ScaleDown runs only where a caller asks for `provider: "scaledown"`.
- **None of TypeSafe, Laya, XOR, SubQ, Perplexity, Cloudflare Clef, OpenAI
Decisions or ScaleDown:** everything behaves exactly as it did without a decision model.
---
## Limits
**The window is small.** Laya's encoders read 1,024 tokens, and 512 on the
`english` checkpoint, against roughly 33,000 for Jev. Part of that is reserved
for each question and its options, so NeuroLink allows about 768 tokens of
state on `typed-decisions` and `multilingual`, and 320 on `english`, `auto` and
any model name it does not recognise. Laya's server does not refuse a longer
state — it answers from the start of it and says nothing — so NeuroLink
refuses it instead, before any network call, with `max_tokens_exceeded`.
The size is an estimate, not Laya's tokenizer: about four characters per token
for ASCII text, and 1.5 tokens per character for other scripts (0.6 on
`multilingual`), calibrated against a live Laya 0.3.5 server. It errs toward refusing. Built-in
consumers treat a refusal as "carry on as before", which means long-prompt
model routing usually falls back to the heuristic when Laya is the only
decision provider.
**Many options degrade it.** A `choice`'s options share a fixed token budget,
so accuracy drops past about 20 options; some Laya servers also reject a
question whose options overflow the budget, as `invalid_request`.
**Pick the checkpoint deliberately.** Laya's own benchmark puts its general
`english` and `multilingual` checkpoints close to chance on typed decisions
without fine-tuning; `typed-decisions` is the fine-tuned one, which is why it is
the default.
---
## Errors
| Reply | Kind | Retried |
| ----------------------------------------------- | ------------------------------------------------------- | ------- |
| 401 / 403 from the proxy | `authentication` — the provider instance stops retrying | no |
| 400 / 422 from Laya | `invalid_request`, with Laya's reason | no |
| 413 from Laya | `max_tokens_exceeded` | no |
| 429 | `rate_limit` | yes |
| 503 | `overloaded` | yes |
| other 5xx | `server` | yes |
| more questions or state than Laya reads (local) | `max_tokens_exceeded`, with no network call | no |
| no base URL configured (local) | `invalid_request`, with no network call | no |
LiteLLM's 401 text echoes a masked copy of the rejected key and its hash; the
provider drops that part before the message reaches a log or an error.
---
## Running your own Laya server
Laya's example server exposes the same `/predict` route. Point
`LAYA_BASE_URL` at it:
```bash
pip install "laya[serve]"
python examples/server.py # from the Laya repository; serves :8000
export LAYA_BASE_URL=http://127.0.0.1:8000
```
---
## Troubleshooting
- **`Laya requires a base URL`** — set `LAYA_BASE_URL`, or pass
`credentials.laya.baseURL`. There is no default endpoint.
- **`Authentication failed`** — the proxy rejected the key. Check it in the
LiteLLM Dashboard, including its Allowed Routes. The provider instance does
not retry after a rejection.
- **A 403 with `error code: 1010`** — Cloudflare in front of your proxy blocked
the client by its signature. Node's `fetch` is accepted; a proxy or agent that
rewrites the user agent may not be.
- **`exceeded the provider's token limit`** — the state is larger than Laya
reads. Shorten it, or configure TypeSafe for long inputs.
- **Built-in routing never uses Laya** — a TypeSafe key is also set and takes
precedence, or Laya has no base URL.
---
## See also
- [The `decide` inference type](../../features/decide-inference-type.md)
- [TypeSafe (Jev) Provider Guide](typesafe.md)
- [XOR Provider Guide](xor.md)
- [Perplexity Decisions Provider Guide](perplexity-decider.md)
- [Cloudflare Clef Provider Guide](cloudflare-clef.md)
- [SubQ Provider Guide](subq.md)
- [OpenAI Decisions Provider Guide](openai-decisions.md)
- [ScaleDown Provider Guide](scaledown.md)
- [Laya on GitHub](https://github.com/NandhaKishorM/laya)