// the llm ops platform
Trust your agents in production.
Build your prompt or agent as an Agentic Function. Functional AI evaluates it, runs it, and traces every call, and you ship new versions anytime, straight from your code.
Both on every plan. SDKs on GitHub
Most LLM ops tools hand you a dashboard to operate. Functional AI evaluates, runs and traces the agent, and hands you a function you can trust in production.
// the problem
Shipping AI is easy. Trusting it in production is not.
It breaks and nobody notices
A prompt tweak quietly regresses. You find out when a customer does, not when it shipped.
The bill creeps and nobody knows why
A chattier model, a bigger prompt, an agent that loops one step too many. Spend climbs, and nobody can say what one run actually costs.
It does something it shouldn't
An agent issues a refund before anyone approved it, or fires the same tool twice. You find out from the customer.
Your software is reliable. Your AI should be too.
// the platform
You shouldn't have to babysit AI in production.
Functional AI is the LLM ops platform for prompts and agents: evaluation, runtime and observability in one place. You write the Agentic Function; we run everything behind it. No platform team required.
your code
result = classify.run(subject=subject, body=body)Hosting
No servers to run. Your Agentic Function lives on our infrastructure.
Your own keys
Amazon Bedrock, Anthropic, OpenAI or Google. Your provider bills the tokens; we never mark them up. No lock-in.
Files in
Attach knowledge files your agent can read. Callers send PDFs and images, passed to the model natively.
Evaluation
No eval harness to build. Measure every version before you ship it, then decide what goes live.
Tools
Any REST API or MCP tool. Test it against the real endpoint before you save it, then add guards and call limits.
Versioning
No redeploys. New versions go live behind the same function call.
Tracing
Every call traced: input, output, each tool call, latency and cost.
Cost per run
Compare models side by side, with the cost of one run on each, before you pick one.
All the agents, none of the infrastructure.
// how it works
Three steps to AI you can trust.
No platform team. No eval pipeline to build. No infrastructure to run. Write it, test it, and call it.
- 01
Write it
Your prompt or agent as an Agentic Function, with a typed input and output. In the canvas, a YAML file, the SDKs, or from your coding agent over MCP.
- 02
Test it
Run it over a dataset on several models at once. Read the trust score, the cost per run, and the findings, each with a fix for the prompt.
- 03
Deploy & call it
We host it. Ship new versions with no app redeploy, and roll back instantly. The URL and keys never change.
// two ways to start
Build it yourself. Or build it with us.
Self-serve
Your engineers, the docs, the SDKs and MCP. Define the Agentic Function, run the experiments, deploy when the trust score says so.
Forward deployed engineering
An engineer from the team that built the platform gets one agent to production with you, or improves one you already run: tools, the first dataset and Score Set, experiments until it is ready, deploy with your team holding the keys, then hands over.
When our engineer leaves, nothing breaks: every version, dataset and experiment is in your account.
// write
Three ways in. One Agentic Function out.
Build in the browser, in code, or from your coding agent. However you start, you end up with the same definition: a typed Agentic Function we host and you call. Each version records which way it came in.
Canvas
Build and test an Agentic Function in the browser, step by step. No setup.
SDK & YAML
Write the definition in Python, TypeScript or Go, with every line checked as you write it. Or keep it in a YAML file and push it with the CLI.
$ fn new function.yaml
MCP
Your AI coding agent builds and tests over MCP, with your permissions. There is no deploy tool: a human ships.
// evaluate & iterate
Test it. Tune it. Until the output and the cost are right.
Run a version over a dataset on several models at once. Each model gets a trust score, a pass rate, cost per run and p95 latency, and every finding comes with a fix for the prompt, not just a number. You read the results and decide what ships.
Quality
Score against datasets of real inputs and expected outputs. Enum outputs get a confusion matrix.
Consistency
Repeat every run. Stability is measured field by field, with no labels needed.
Model choice
Several models in one experiment, each with its cost per run, before you pick one.
Compared to what's live
A drop against the deployed version is flagged before you deploy. You decide.
// agent tests
Your agent's definition writes its own safety tests.
A right answer can still come from the wrong path: a refund before approval, a tool called twice. Every guard, call limit and effect you declare becomes a behaviour check, run in every experiment, so the definition is proven before it touches a real order.
tools:
- name: lookup_order
max_calls: 3
- name: human_approval
config: { prompt: "Approve this above-limit refund?" }
- name: issue_small_refund
config: { max_amount: 100 }
max_calls: 1
effect: side_effecting
- name: issue_refund
requires: "human_approval.returned.approved == true"
effect: side_effecting✓ issue_refund never called before human_approval returns approved
from requires
✓ issue_small_refund never called twice in a run
from max_calls: 1
✓ lookup_order called at most 3 times
from max_calls: 3
✓ No side-effecting call repeated with the same arguments
from effect: side_effecting
Tools are mocked per test row. An agent that issues refunds can be tested a thousand times without issuing one.
// deploy & call
Deploy a version. Then just call it.
Deploy a version and you get a stable, authenticated HTTP endpoint, hosted on our infrastructure. Send inputs, get typed output, a status, and the trace ID and metadata you need to bill, trace, and debug.
{ "output": { "queue": "billing", "priority": 2, "reason": "Charged twice for the March invoice." }, "status": "success", "meta": { "version": 3, "latency_ms": 1840, "cost_usd": 0.0021, "tokens_in": 812, "tokens_out": 96, "trace_id": "tr_8f3c2a1d" } }
Four statuses, no guessing
successpartialescalatedfailed
An agent out of steps returns its best answer as partial. One that asks a human returns escalated. Your code branches on the status.
Bad input costs nothing
Input that breaks the contract is rejected with a 422 naming the field, before any model call and before any tokens.
// observe
Every call, every step, and a button that turns a failure into a test.
Each production call is recorded step by step, by version and by key. When one goes wrong you see exactly which tool did what, and every production failure becomes a test in two clicks.
Every call traced
Input, output, status, model, cost and tokens, plus every step: each tool call with its arguments, result, latency and any error.
Attention filter
One filter for the calls that need a look: failed, throttled, partial and escalated.
Flag to test
A bad production call becomes a dataset row in two clicks, so the next version is tested against it.
// reliability
When a tool fails, the agent degrades. It doesn't guess.
Real tools and networks fail. Functional AI bounds every run, retries only what is safe to retry, and when an agent can't finish, it says so with a status instead of inventing an answer.
Retries by effect
Only read-only and idempotent tools are retried. A side-effecting call, a charge or a send, is never fired twice.
Bounded loops
Every agent run has a step budget, 12 by default, and max_calls locks a tool when its cap is hit. Out of steps, you get status partial with the reason.
Tool failures are information
A failed tool call goes back to the agent as an error, not a crash, so it can try something else. Every tool call times out after 30 s.
Escalation
When an agent calls human_approval, the run stops with status escalated. You collect the decision and re-run with it.
// security
Agents touch the outside world. We contain the blast radius.
The moment an Agentic Function fetches a web page or calls a tool, it has an attack surface. We won't claim prompt injection is solved; it isn't. So Functional AI limits what a manipulated agent can reach: tools it cannot see, credentials it never holds, networks it cannot call.
Guarded tools are invisible
A tool with requires is hidden from the model until its condition holds. Safety comes from the runtime, not the prompt.
No credentials in the runtime
Tool credentials live in a gateway, never where the agent runs. There is nothing in the runtime worth stealing.
Private network refused
Loopback, private and cloud-metadata addresses are refused for every tool call, platform or your own.
Sensitive fields redacted
Fields marked sensitive are redacted from traces before they are stored.
// ship new versions anytime
Ship a better version at 2pm. No redeploy.
The same function call picks up the new version behind it, so you ship improvements without redeploying your app. What you tested is what runs: each version compiles to one hashed artifact. Diff any two, and roll back instantly when production tells you to.
- DraftEdited in place until you're happy.
- ReadyIts Contract Test passed. Testable, deployable.
- LiveDeployed, and frozen for good. Changes make a new version.
instant rollback
$ fn rollback 42 --to-version 317No rebuild. The URL and keys never change.
// with Functional AI
Two ways to run AI in production.
The difference between hoping your AI holds up and knowing it does.
Without Functional AI
- Prompts scattered across Notion, env vars, and your codebase
- You find out it broke from a customer
- Agent behaviour tested in production, on real orders
- Costs creep up and nobody knows what one run costs
- Locked into one model; a price hike or deprecation is your problem
- Changing the AI means a full redeploy
With Functional AI
- Measured against the last version before you ship
- Agent behaviour tested without touching real systems
- One Agentic Function you call from your code
- Roll back in one command
- Your own model keys, no markup
- Ship new versions anytime, no redeploy
No platform team required. Your engineers own the agent end to end.
// faq
Common questions
- What is the best way to host an agent as an Agentic Function?
- Define it once, in the canvas, in a YAML file pushed with the fn CLI, or with the Python, TypeScript or Go SDK, as a Prompt function (one model call, typed in and typed out) or an Agent (loops with tools until its answer satisfies the output contract, within a step budget). Functional AI hosts each deployed version behind a stable HTTP endpoint: your app sends the input with an invoke key and gets typed output, a status, and metadata back. Input that breaks the contract is rejected with a 422 naming the field, before any model call. Shipping a new version never needs an app redeploy.
- How do I test an agent before it touches real systems?
- Run an experiment over a dataset with the agent's tool responses mocked or replayed per row, so no test ever reaches a real system. Functional AI generates behaviour checks from the agent's own definition: issue_refund is never called before human_approval returns approved, a tool capped at max_calls: 1 is never called twice, and no side-effecting call is repeated with the same arguments. Evaluators for tool selection, tool arguments, path, step efficiency, task completion and escalation sit alongside them. An agent that issues refunds can be tested a thousand times without issuing one.
- How do I add a human approval step to an agent?
- Give the agent the built-in human_approval tool and guard the risky tool with requires, for example requires: "human_approval.returned.approved == true". A guarded tool is invisible to the model until its condition holds, so the safety comes from the runtime, not the prompt. When the agent calls human_approval, the run stops with status escalated; your app collects the decision and re-runs with it in the context.
- How do I choose the best model for an agent?
- Run one experiment across several models on the same version, dataset and Score Set. Each model gets a trust score out of 100, a pass rate, cost per run and p95 latency, plus findings that each come with a concrete fix for the prompt. You compare the results and pick the model when you deploy. The model is not part of the definition, so changing it later is a new deploy, not a code change. Calls run on your own Amazon Bedrock, Anthropic, OpenAI or Google key, and we never mark tokens up.
- How do I ship a new prompt version without redeploying my app?
- Your app calls the same Agentic Function endpoint with the same invoke key every time. Edit the definition, test the new version, and deploy it from the app or with fn deploy. The endpoint starts serving the new version and your code does not change. Each version compiles to one hashed artifact, so what you tested is what runs.
- How do I version and roll back prompts in production?
- Every Agentic Function has versions that move from Draft to Ready (once its Contract Test passes) to Live (once deployed). The first deploy freezes a version for good, and fn diff shows what changed between any two. To roll back, use fn rollback or the button in the app to return to the previous or any earlier live version. Rollback is instant, needs no rebuild, and the URL and keys never change.
- Can you build the agent for us?
- Yes. Forward deployed engineering is available on every plan, including Pro, and priced per engagement with a fixed scope: get one agent to production, or improve an existing agent. An engineer from the team that built the platform registers your tools, writes the first dataset and Score Set, builds and iterates until the experiments say it is ready, deploys with your team holding the keys, and hands over. Every version, dataset and experiment is in your account, so your engineers own it from there. When our engineer leaves, nothing breaks. Enterprise plans include engineering hours.
Build agents you can trust. Start today.
Tell us what you want to ship and whether you want to build it yourself or with an engineer. We set up your account and reply.