// INTENT → ACTION

Natural language in,
tool calls out.

Describe your API. Fernfly writes the training data, fine-tunes a small model on your tool set, and mints an endpoint that returns a validated call. One HTTP request, no prompt engineering, and no per-token bill.

$0
cost per request
<1s
typical response time
85%
accuracy out of the box, higher once retrained
POST /api/p/YOUR_PROJECT_ID/infer
// natural language in
“move my 3pm standup to Thursday”
// tool call out
reschedule_event({
event: "Standup",
to: "2026-07-09T15:00"
})
exact match· under 1s · $0
The contract

One endpoint, one shape

Post an utterance with your project key. Get back the calls to run, in the order to run them, or an empty list when the model declines rather than guesses. That is the whole surface.

Request
POST /api/p/YOUR_PROJECT_ID/infer
X-Api-Key: YOUR_PROJECT_KEY
Content-Type: application/json

{
  "utterance": "move my 3pm standup to Thursday",
  "meta": { "user_id": "u_1042" }
}
Response
{
  "calls": [
    {
      "name": "reschedule_event",
      "arguments": {
        "event": "Standup",
        "to": "2026-07-09T15:00"
      }
    }
  ]
}
The argument

Why not just prompt a frontier model

You can, and for a handful of calls a day you probably should. The economics invert once the same bounded intent runs thousands of times: a general model re-reads your entire tool schema on every call, and you pay for those tokens every time.

The schema is not re-sent

Tools are registered once and referenced by id. A frontier call pays for the full spec as input tokens on every request.

One hop, not a plan

Intent to action is a single classification with arguments. No planning loop, no chain of thought, no retry budget.

Small enough to sit anywhere

A 12M-parameter model runs on ordinary CPU hardware, which is what makes on-premises and offline deployment possible at all.

Do not take the claim on trust. The playground runs the same curated tasks through a Fern use-case model and through GPT-4o side by side, and reports accuracy, schema conformance, latency, and the frontier cost per run.

Open the playground
Under the hood

What happens after you click train

01

Register the tools

Your tool schema is uploaded once and content-addressed to a tool_set_id. Training lines and inference calls then reference the id instead of re-sending tens of KB of JSON Schema on every request.

02

Generate the training set

Gemini writes candidate utterance-to-call pairs from your schema, including negatives for anything out of scope. You review, edit, and approve them before they become training data.

03

Fine-tune

Approved pairs become OpenAI-shaped JSONL and a fine-tuning job on the Fern inference API. Epochs, batch size, and learning rate default from a pair-count heuristic and can be set explicitly.

04

Deploy and version

A deployment pins one fine-tuned model id. The stable per-project endpoint always routes to the active deployment; the per-deployment endpoint pins a version, so you can hold traffic on a known-good model while you retrain.

Models

Three base models, all fine-tunable

Fern Bud

12M params
fern-bud-1.0

Where a project starts unless you say otherwise. Trains in minutes and runs comfortably on a CPU.

Fern Pinnule

160M params
fern-160m

More accurate once the tool set grows past what a 12M model holds comfortably. Slower to train and slower to answer.

Fern Pinna

1.5B params
fern-1500

The accuracy ceiling, and what our own templates train on. Slowest to train and to answer.

Hyperparameters are yours if you want them

Base model, epochs, batch size, and learning rate all default from the size of your approved training set, and the wizard pre-fills them. Set them explicitly if you have a reason to. They are fixed once the project has trained, so a retrain reproduces the same configuration.

Integration

Three ways to put it in front of users

The embed widget

One script tag. The bubble renders on your site, calls the keyless endpoint, and is constrained by your origin allow-list.

Best for a website assistant

Your own backend

POST the utterance with a project key, get the call back, and execute it yourself against your API with your own auth and permissions.

Best for a product surface

Inside your network

The model is small enough to run on your hardware, so conversations never leave the building. Talk to us about a private deployment.

Best for regulated data
Behaviour

What it does at the edges

  • Out-of-scope utterances resolve to a sentinel rather than a wrong call, so your executor never receives a tool you did not train.
  • An empty call list is a first-class answer. The model declining is a better outcome than a plausible guess.
  • A cloud fallback can answer anything the model declines, and it is a per-project switch you own.
  • Job status is pulled live from the training backend, so a run that fails upstream surfaces in your dashboard rather than hanging.
Controls

Who may call, and how often

Two auth modes

Server-to-server with a project API key, or keyless for the browser widget. Key-authed traffic skips the origin check and the rate limit; keyless traffic gets both.

Origin allow-list

Keyless projects answer only the domains you list, and the CORS grant reflects the caller instead of a wildcard. Requests with no Origin header fall through to the rate limit, since Origin is trivially forged outside a browser.

Per-caller rate limit

20 requests a minute per caller per project on the keyless endpoint, counted in the database so the window is shared across workers and survives a reload.

Every call logged

Latency, the resolved call, the fallback path, and a salted caller hash. The analytics tab rolls it up; the history tab lists it one row at a time.

Worked example

One we built and shipped

Hoobert is a ⌘K command bar for WooCommerce, live on the WordPress.org plugin directory. It is an ordinary Fernfly project: 28 store actions, one endpoint, and a plugin that executes the returned call through the WooCommerce REST API with the shop manager's own permissions.

Your traffic is the next training set

Every request is logged with what the model resolved it to, and the ones it declined are collected as the retraining queue. Approve them, retrain, and cut a new deployment. The previous version keeps serving until you switch, so there is no window where the endpoint is down.

Start free

Point it at your API

Free to start, no credit card, and the first endpoint is live in an afternoon.