Open to everyone: start free, no card

Build AI applications.Skip the infrastructure.

Agents, tools, knowledge, memory, sandboxes and coding agents. Describe them in a folder, deploy with one command, and Maitento runs them, on your own model keys.

npm install @maitento/sdk
pip install maitento
dotnet add package Maitento.Sdk
  • Agents
  • Tools
  • Secrets
  • Knowledge
  • Memory
  • Approvals
  • Teams
  • Swarms
  • Apps
  • Sandboxes
  • Schedules
maitento/agents/greeter.mtr
// An agent: a model and its instructions.
model = @ref("deepseek.deepseek-v4-flash")
prompt = "You are a friendly assistant. Keep every answer to one or two sentences."
summary = "A friendly assistant"
maitento/interactions/one-shot/hello.mtr
// A one-shot interaction: one agent, one task, one answer.
agent = {
  name = "Greeter"
  agent = @ref("greeter")
}
task = "Hello, how are you?"
maitento/hello.ts
import { Maitento } from "@maitento/sdk";

const mt = new Maitento();
await mt.deploy("./maitento");

const run = await mt.interactions.run("hello");
console.log(run.output);
maitento/hello.py
from maitento import Maitento

mt = Maitento()
mt.deploy("./maitento")

run = mt.interactions.run("hello")
print(run.output)
maitento/Hello.cs
using Maitento.Sdk;

await using var mt = MaitentoClient.CreateFromEnvironment();
await mt.DeployAsync("./maitento");

var run = await mt.Interactions.RunAsync("hello");
Console.WriteLine(run.Output);
terminal
  1. mt deploy ./maitento
  2. Discovered greeter in agents
  3. Discovered hello in interactions/one-shot
  4. Created: Agent greeter
  5. Created: OneShotInteraction hello
  6. Deployed to namespace 'tutorials' in 327ms: 2 created.Deployed
  7. mt interaction-run hello
  8. Status: RunningRunning
  9. [Greeter] I am functioning well, thank you for asking. How may I assist you today?
  10. Status: FinishedFinished
  • Agents
  • Tools
  • Secrets
  • Knowledge
  • Memory
  • Approvals
  • Teams
  • Swarms
  • Apps
  • Sandboxes
  • Schedules
maitento/external-operations/open-api/find-order.mtr
connector = @ref("shop-order-get")
// Maitento sends the secret's value in this header.
// The model never sees it.
auth = {
  header = "X-Api-Key"
  secret = @ref("shop-api-key")
}
guidance = "Looks up an order: who placed it, each item and its price, the status and how much has been refunded."
maitento/interactions/one-shot/draft-reply.mtr
agent = {
  name = "Desk"
  agent = @ref("desk-agent")
}
task = @prompt("draft-reply-task")
functions.openApi = [
  {
    name = "find-order"
    ref = @ref("find-order")
  },
  {
    name = "search-policies"
    ref = @ref("search-policies")
  }
]
// The knowledge base comes in with each run and goes
// straight into the search: the model can't choose another.
inputs.functions.binding = [
  {
    function = @ref("search-policies")
    name = "policiesId"
    target = "partitionId"
    type = "request"
  }
]
example run · draft-reply
  1. runRunning
  2. toolfind-order {"orderId":"A-1001"}
  3. ↳Hand grinder £42.00 · delivered yesterday
  4. toolsearch-policies {"query":"faulty item refund"}Knowledge
  5. ↳“A faulty item is refunded in full within 30 days.”
  6. DeskI’m sorry the handle snapped, Sam. A faulty grinder is covered: I can refund the £42.00 in full.
  7. runFinished2 tool calls
  • Agents
  • Tools
  • Secrets
  • Knowledge
  • Memory
  • Approvals
  • Teams
  • Swarms
  • Apps
  • Sandboxes
  • Schedules
maitento/interactions/one-shot/draft-reply.mtr
// One memory per customer, chosen by their email address.
loom = {
  enabled = true
  scope = "Input"
  scopeInput = "email"
  subjectInputs = [ "customer" ]
  recall = "Suggest"
  weave = "Manual"
}
maitento/external-operations/open-api/issue-refund.mtr
connector = @ref("shop-order-refund")
auth = {
  header = "X-Api-Key"
  secret = @ref("shop-api-key")
}
guidance = "Refunds an order. Refund only what the policies allow, and never more than was paid for the item."
// A person approves every refund before Maitento calls it.
requiresApproval = true
example run · draft-reply
  1. memorySam Lee: prefers email · bought the grinder on 24 Oct
  2. toolissue-refund {"orderId":"A-1001","amount":42.00}
  3. runPendingApproval: a person approves every refundWaiting
  4. personApproved
  5. ↳Refunded £42.00
  6. DeskDone, Sam: £42.00 is on its way back to your card.
  7. memoryWoven: “Sam’s faulty grinder was refunded in full.”
  8. runFinishedWaiting not charged
  • Agents
  • Tools
  • Secrets
  • Knowledge
  • Memory
  • Approvals
  • Teams
  • Swarms
  • Apps
  • Sandboxes
  • Schedules
maitento/interactions/one-shot/compare-countries.mtr
agent = {
  name = "LeadResearcher"
  agent = @ref("lead-researcher")
}
task = "Compare these countries: %%countries%%. Start one country-facts interaction per country so they run in parallel, wait for them all, then write a short comparison."
// The interactions this one may start as sub-runs, and how many at once.
swarm = {
  interactions = [
    @ref("country-facts")
  ]
  maxConcurrent = 5
  maxTotal = 10
}
maitento/interactions/managed/newsletter.mtr
// The manager gets the task and hands out work.
manager = {
  name = "Editor"
  agent = @ref("editor")
}
agents = [
  {
    name = "Writer"
    agent = @ref("writer")
    // Keeps its own conversation with the editor.
    mode = "Private"
  },
  {
    name = "FactChecker"
    agent = @ref("fact-checker")
    // A fresh fact checker every time it is asked.
    mode = "OneTime"
  }
]
limits.maxDispatches = 8
example run · compare-countries
  1. runRunning
  2. LeadStarting four country-facts sub-runs in parallel.
  3. sub-runcountry-facts · JapanFinished
  4. sub-runcountry-facts · BrazilFinished
  5. sub-runcountry-facts · KenyaFinished
  6. sub-runcountry-facts · NorwayFinished
  7. LeadBrazil is by far the largest; Norway the smallest by population. Here is how they compare…
  8. runFinished4 sub-runs
  • Agents
  • Tools
  • Secrets
  • Knowledge
  • Memory
  • Approvals
  • Teams
  • Swarms
  • Apps
  • Sandboxes
  • Schedules
maitento/apps/nightly-digest/nightly-digest.mtc
string main(string namespaceName) {
  string day = DateTimeToString(DateGetUtc(), "yyyy-MM-dd");

  // Call your app through a tool: Maitento adds the secret.
  jsonObject path = JsonObjectCreate();
  path = JsonObjectSetString(path, "date", day);
  string response = ExtOpInvoke("list-tickets", "", "", path, "");

  // Save them where the capsule can read them.
  VfsWriteText("support-desk", namespaceName, "/tickets/" + day + ".json", response);

  // A throwaway Linux machine turns them into a report.
  guid capsuleId = CapsuleStart("ticket-report", namespaceName, "[]", "[]", "[]");
  jsonObject capsule = CapsuleAwait(capsuleId);

  string report = VfsReadText("support-desk", namespaceName, "/reports/latest.md");
  AppStateSetOutputString("report", report);
  return("Digest written for " + day);
}
maitento/capsules/ticket-report.mtr
// A throwaway Linux machine that runs a script on the day's tickets.
autoTerminate = true
maxDuration = "00:05:00"

vfs = [
  {
    vfs = @ref("support-desk")
    mountName = "desk"
  }
]

startup = [
  {
    command = "python3"
    arguments = ["/mnt/desk/count_tickets.py"]
    wait = true
    maxDuration = "00:02:00"
  }
]
example run · nightly-digest
  1. appnightly-digest started by its schedule
  2. toollist-tickets {"date":"2026-10-30"}
  3. ↳Tickets on 2026-10-30: 37
  4. filesupport-desk:/tickets/2026-10-30.json
  5. capsuleticket-report · python3 count_tickets.py
  6. capsuleFinished · /reports/latest.md writtenSandbox
  7. appDigest written for 2026-10-30Finished

An agent is a model and its instructions; an interaction gives it a job. Two small files and one deploy. Tutorial 1

Your API becomes the agent’s tools, with your secret added by Maitento. A search over your own documents answers from your policies, and the knowledge base comes from the run: bound out of the model’s reach. Tutorials 8–13

One memory per customer, chosen by their email, so the agent wakes up knowing who it is talking to. The refund tool waits for a person, and time spent waiting is never charged. Tutorials 10 and 20

A manager hands work to a writer and a fact-checker. A lead researcher starts a swarm of sub-runs in parallel, waits for them all, and combines what comes back. Tutorials 18 and 19

An app chains the steps: it calls your API, writes files, starts a throwaway Linux machine to crunch them, and returns the report. On a schedule, with nothing to host. Tutorial 23

Your models, your keys

Bring your own model keys. We never charge for tokens.

$0on model tokens: your provider bills you directly
Per secondand only while running, never while queued or waiting for a person
Unlimitedusers on every plan: no per-seat pricing
  • OpenAI
  • Anthropic
  • Gemini
  • DeepSeek
  • Qwen
  • GLM
  • Kimi
  • Azure OpenAI
  • Azure AI Foundry
  • Your own endpoint

The building blocks

One platform for everything your AI app does

Write each piece as a small project file. Maitento compiles them, runs them, and keeps them running.

Agents and teams

An agent is a model and its instructions. Put several together: a router that hands each turn to a specialist, a round-robin chat, or a manager splitting work across a team.

Learn more

Tools from any API

Point a connector at an OpenAPI operation and it becomes a tool your agents call, with its secret, its guidance, and a person’s approval when it matters.

Learn more

Knowledge

Upload documents and search them by meaning. Chunking, embedding and vector search are built in.

Learn more

Memory

A loom gives an agent long-term memory: who it’s talking to, what they care about, what was decided.

Learn more

Sandboxes

Capsules are throwaway Linux machines with time limits, for running real code against real files.

Learn more

Coding agents

Code pipelines run Claude Code, Codex, Gemini CLI and others on your repositories, in a sandbox, and push a branch. Hooks send work back until the tests pass.

Learn more

Apps, schedules and webhooks

Chain steps into an app, run it on a schedule or from your code, and get a signed webhook when anything finishes.

Learn more

Web search and reading

Built-in tools search the web and read pages, PDFs, Office documents and images, with no connector to write.

Learn more

See every run

Every run’s conversation, tool calls, timing and tokens, live over events and in the portal, from the first token to the last.

Learn more

Zero infrastructure

Everything an AI app needs, already running

Long-running agents need far more than a model call. Maitento runs all of it for you, so your repository holds what your application does, not how it stays up.

What you'd otherwise build and run

  • Queues and workers for long runs
  • A vector database
  • Sandboxed machines for code
  • A scheduler for recurring jobs
  • Webhook delivery and retries
  • A secrets store
  • Run logs and traces
  • Retries for every model provider
  • Memory between conversations
  • Approval steps for risky actions

What you write with Maitento

maitento/
├─ agents/         desk-agent.mtr
├─ interactions/   answer-ticket.mtr
├─ apps/           nightly-digest/
├─ capsules/       ticket-report.mtr
├─ code-pipelines/ add-feature/
└─ connectors/     shop-orders.mtr
$ mt deploy ./maitento Deployed in 327ms

What you can build

Real applications,
not hello worlds

Each one is built step by step in the tutorials, and each is a handful of small files.

A support desk that knows when to ask

Triages every ticket, looks up the order through your API, answers from your policies, remembers each customer, and stops for a person before any refund. A nightly app runs a sandbox to write the day’s report.

  • Agents
  • Tools
  • Secrets
  • Knowledge
  • Memory
  • Approvals
  • Apps
  • Sandboxes
Tutorial 23: build the whole support desk
maitento/external-operations/open-api/issue-refund.mtr
connector = @ref("shop-order-refund")
auth = {
  header = "X-Api-Key"
  secret = @ref("shop-api-key")
}
guidance = "Refunds an order. Refund only what the policies allow, and never more than was paid for the item."
// A person approves every refund before Maitento calls it.
requiresApproval = true
maitento/interactions/one-shot/draft-reply.mtr
agent = {
  name = "Desk"
  agent = @ref("desk-agent")
}
task = @prompt("draft-reply-task")
functions.openApi = [
  {
    name = "find-order"
    ref = @ref("find-order")
  },
  {
    name = "search-policies"
    ref = @ref("search-policies")
  }
]
// The knowledge base comes in with each run and goes
// straight into the search: the model can't choose another.
inputs.functions.binding = [
  {
    function = @ref("search-policies")
    name = "policiesId"
    target = "partitionId"
    type = "request"
  }
]
// One memory per customer, chosen by their email address.
loom = {
  enabled = true
  scope = "Input"
  scopeInput = "email"
  subjectInputs = [ "customer" ]
  recall = "Suggest"
  weave = "Manual"
}
maitento/apps/nightly-digest/nightly-digest.mtc
string main(string namespaceName) {
  string day = DateTimeToString(DateGetUtc(), "yyyy-MM-dd");

  // Call your app through a tool: Maitento adds the secret.
  jsonObject path = JsonObjectCreate();
  path = JsonObjectSetString(path, "date", day);
  string response = ExtOpInvoke("list-tickets", "", "", path, "");

  // Save them where the capsule can read them.
  VfsWriteText("support-desk", namespaceName, "/tickets/" + day + ".json", response);

  // A throwaway Linux machine turns them into a report.
  guid capsuleId = CapsuleStart("ticket-report", namespaceName, "[]", "[]", "[]");
  jsonObject capsule = CapsuleAwait(capsuleId);

  string report = VfsReadText("support-desk", namespaceName, "/reports/latest.md");
  AppStateSetOutputString("report", report);
  return("Digest written for " + day);
}

A lead researcher with a swarm of its own

One agent splits a big question into small ones, starts a sub-run for each in parallel, waits for them all, and combines the answers. Each child has its own time limit, and never outlives its parent.

  • Agents
  • Swarms
  • Limits
Tutorial 18: sub-interactions
maitento/interactions/one-shot/compare-countries.mtr
agent = {
  name = "LeadResearcher"
  agent = @ref("lead-researcher")
}
task = "Compare these countries: %%countries%%. Start one country-facts interaction per country so they run in parallel, wait for them all, then write a short comparison."
// The interactions this one may start as sub-runs, and how many at once.
swarm = {
  interactions = [
    @ref("country-facts")
  ]
  maxConcurrent = 5
  maxTotal = 10
}
maitento/agents/lead-researcher.mtr
model = @ref("deepseek.deepseek-v4-flash")
prompt = "You split big research jobs into small ones, run them in parallel, then combine the answers. If a piece of research fails, say which one failed and why. Never fill the gap from your own memory."
summary = "Splits research into parallel sub-tasks"
// Lets this agent start other interactions as sub-runs.
allowSwarm = true
maitento/interactions/one-shot/country-facts.mtr
// The child: researches one country.
agent = {
  name = "CountryResearcher"
  agent = @ref("country-researcher")
}
task = "Give three short facts about %%country%%: population, capital and one thing it is famous for."
inputs.prompts = [
  {
    name = "country"
    required = true
  }
]
// A child never runs past the time its parent has left.
duration.max = "00:02:00"

A managed team: an editor, a writer and a fact-checker

The editor plans the issue and dispatches work; the writer keeps its own conversation with the editor, and every fact check starts fresh. Team members only see what the manager sends them.

  • Agents
  • Teams
  • Limits
Tutorial 19: managed teams
maitento/interactions/managed/newsletter.mtr
// The manager gets the task and hands out work.
manager = {
  name = "Editor"
  agent = @ref("editor")
}
agents = [
  {
    name = "Writer"
    agent = @ref("writer")
    // Keeps its own conversation with the editor.
    mode = "Private"
  },
  {
    name = "FactChecker"
    agent = @ref("fact-checker")
    // A fresh fact checker every time it is asked.
    mode = "OneTime"
  }
]
limits.maxDispatches = 8
maitento/agents/editor.mtr
model = @ref("deepseek.deepseek-v4-flash")
prompt = "You are a newsletter editor. You plan the issue, hand work to your team with the Dispatch tool, and decide when it is good enough. Your final reply must be the finished newsletter and nothing else: no notes about the edits."
summary = "Plans and edits the newsletter"

A coding agent that tests its own work

A developer agent changes your repository in a sandbox; a tester runs the tests in a fresh session; a hook reads the report and sends the work back until the tests pass, then a branch is pushed.

  • Coding agents
  • Sandboxes
  • Hooks
  • Limits
Tutorial 22: code pipelines
maitento/code-pipelines/tested-change/pipeline-definition.json
{
  "name": "tested-change",
  "durationAutoTermination": "00:45:00",
  "maxFixIterations": 2,
  "agents": [
    { "name": "developer", "role": "Fullstack" },
    { "name": "tester", "role": "Reviewer" }
  ],
  "phases": [
    {
      "name": "implement",
      "steps": [{
        "name": "implement",
        "agentName": "developer",
        "prompt": "@prompt(implement)",
        "isCommitable": true
      }]
    },
    {
      "name": "test",
      "dependsOn": ["implement"],
      "postHook": "TestGate",
      "steps": [{
        "name": "run-tests",
        "agentName": "tester",
        "prompt": "@prompt(run-tests)",
        "isNewSession": true,
        "outputVariableName": "testReport"
      }]
    }
  ]
}
maitento/code-pipeline-hooks/tested-change/tested-change.mtc
// The test phase's post hook decides what happens next.
string TestGate(string processId, string methodName) {
  string report = PipelineGetVariable(processId, "testReport");

  // The tests pass: nothing more to do.
  if (StringContains(report, "EXIT CODE: 0", false)) {
    return("{\"decision\": \"done\"}");
  }

  // They fail: loop back. The developer fixes the code with the
  // report in its prompt, then the tests run again, with this hook.
  PipelineLog(processId, "TestGate: the tests failed, looping back to the developer");
  // (fixPhase and retestPhase are the two phases, as JSON: see the tutorial.)
  return("{\"decision\": \"loop\", \"loop\": {\"blockingIssueCount\": 1, \"fixPhases\": [" + fixPhase + ", " + retestPhase + "]}}");
}

A companion that remembers a whole household

Wren shares one memory across everyone in a family: what one person mentions in passing, the next person’s conversation knows. Overnight, the loom weaves what it learned.

  • Agents
  • Memory
  • Conversations
Tutorial 20: memory
maitento/interactions/round-robin/wren-family.mtr
// Every conversation weaves into the one loom in looms/family.mtr,
// so what one person tells Wren, the next person's conversation knows too.
agents = [
  {
    name = "Wren"
    agent = @ref("wren")
    loom = @ref("family")
  }
]
task = @prompt("wren-family")
human = {
  first = true
}
loom = {
  enabled = true
  subjectInputs = [ "userName" ]
  recall = "Suggest"
  weave = "Suggest"
}
maitento/looms/family.mtr
// A loom a whole household shares. Deploying creates it;
// a deploy never touches what it holds.
description = "What Wren knows about the family: shared across everyone who talks to it in wren-family."
nightWeaving = true
quietMinutes = 5

The portal

Build in code.
Watch it in the portal.

Deploy from your editor and CI, then follow every run as it happens: what each agent said, called and changed.

The portal overview: running, waiting and failed runs across interactions, capsules, code pipelines and apps, with what needs attention and what is live nowAn interaction run waiting for approval of a board-move-item tool call, showing the exact arguments with Reject and Approve and runA managed team run: the manager dispatches work to a teammate in a private conversation, with tokens per participant and the tools usedA code pipeline step transcript: the developer agent reading, editing and writing files and running builds and tests, each with its durationThe diff of a finished code pipeline: six files changed on its own branchA loom tapestry: what the Tech Lead agent wakes up knowing about Lena and Finance, woven within a token budgetThe usage page: tokens and runtime over 30 days by namespaceThe Build studio with a 103-file project open, a round-robin interaction in the editor and a valid build

Built on Maitento

A complete support desk, in 23 lessons

The tutorials end with a real application: a coffee shop’s support desk, with a web app, a phone view and a nightly digest. Every piece of it is a Maitento building block you will have learned.

  • Triages every ticket as it arrives
  • Looks up the order through your shop’s API
  • Answers from your policies, and from the web
  • Asks a person before it refunds anything
  • Remembers each customer across tickets
  • Sends a nightly digest on a schedule
Build the support desk
The support desk: a ticket asking for a refund, waiting for a person to approve itThe support desk on a phone, showing one ticket

For every size of team

Start free.
Pay only while it runs.

No per-seat pricing, and nothing charged on model tokens: your provider bills you for those, on your own key.

Free · Dev

Solo developers

Free, then $29/month

Start on Free with no card. Move to Dev when you want sandboxes, coding agents and more hours.

Start free

Builder · Team

Product teams

From $129/month

Unlimited users on every plan, more runs at once, a discount on everything past your allowance, and a longer run history.

Compare plans

Scale · Enterprise

Scale and enterprise

From $949/month

High volume, scheduled first. Enterprise adds custom pricing, quotas and priority under a contract.

Talk to us

Launch pricing in USD, before tax, billed annually. See every plan and rate.

Security

Agents that act,
with guard rails built in

An agent only sees the surface you give it. Keys, account ids and anything you bind stay with Maitento; code runs in throwaway containers, never in your network; a person approves what matters, and every run is on the record.

How Maitento keeps you safe

What the agent sees

  • find-order(orderId)Looks up an order
  • search-policies(query)Searches the shop’s policies
  • issue-refund(orderId, amount)Refunds an orderneeds approval

No URLs, no keys, no account ids, no other parameters.

What Maitento sends

  • GET https://shop.example/orders/A-1001X-Api-Key: •••••••• from the secret shop-api-keyAdded by Maitento
  • POST knowledge-search{ "partitionId": this run’s knowledge base, "query": "faulty item refund" }Bound from the run
  • POST https://shop.example/orders/A-1001/refundheld until a person approves itApproval

Bound values the model never sees

Fix any parameter the model has no reason to choose: an account, a unit, a flag. Maitento adds it to every call, and the model can’t see it, change it, or be talked into another.

In the docs

Throwaway sandboxes with time limits

Capsules and code pipelines get a fresh container that ends when its commands finish, when you stop it, or when its time runs out. Nothing to host, patch or clean up.

In the docs

Approval before risky actions

Mark a tool as needing approval and the run stops before calling it, until someone approves, or rejects it with feedback the agent can act on. Waiting is never charged.

In the docs

Every run on the record

Each run keeps its conversation, every tool call and its arguments, approvals, timing and tokens, and which of your credentials served it, for as long as your plan’s retention allows.

In the docs

Your model keys, your provider account

Every model call goes to your provider on your own account, under your agreement with them. Give each of your customers their own keys with credential stacks.

In the docs

Encrypted at rest, under your own key

Secrets and credentials are encrypted at rest with AES-256-GCM under a key that belongs to your tenant alone, itself protected by a root key that never sits in the database. One tenant’s key never unlocks another’s.

Get started

Your first agent in five steps

From no account to an agent answering you, with the docs beside you all the way.

  1. 1Create your accountSign up free, with no card.
  2. 2Create an API keyYour code and the CLI use it to call Maitento.
  3. 3Add a model keyYour OpenAI, Anthropic, DeepSeek or other key.
  4. 4Install an SDKTypeScript, Python, C#, or the mt CLI.
  5. 5Run your first agentTwo small files and one deploy.

Using a coding agent?

Give it this prompt. The docs publish an llms.txt and every page as Markdown, made for agents to read.

Set up Maitento in this project. Read https://docs.maitento.com/llms.txt first, then follow https://docs.maitento.com/get-started/. Install the Maitento SDK for this project's language, create a first agent and a one-shot interaction under ./maitento, deploy them and run the interaction. Read my API key and namespace from the MAITENTO_API_KEY and MAITENTO_NAMESPACE environment variables, and never write a key into a file.

Build your first AI application today

Free to start, no card. Your models, your keys, and nothing to run but your idea.