Skip to content
Qosm
Private betaSign In

We built a programming language and runtime for AIs, not humans

February 25, 2026·Pierre Chiche·3 min read
languageagentssecuritycapabilities

For the first time in the history of computing, humans are no longer writing every line of code that runs in production. In a lot of cases, nobody will ever even read it. Every programming language ever built assumed a human was in the loop at least once. Qosm does not make that assumption.

It's a programming language and runtime designed to be read, written, and reasoned about by LLMs. To our knowledge, it's the first language built with that as an explicit goal.

A first taste

Here's a Qosm program. The host provisions two capabilities, http_get and db_insert, and the agent code calls them like any other function:

fetch_and_store.qosmQosm
Provided by host
extern http_get  : {url: String} -> String ! {Http.Get};
extern db_insert : {key: String, value: String} -> Unit ! {Db.Insert};
Agent code
let fetch_and_store url key =
  let data = http_get {url: url};
  db_insert {key: key, value: data};

// The agent can only call http_get and db_insert.
// No file access. No LLM. Nothing else exists.

The host decides what to expose. The agent can only call what it receives. No file access, no environment variables, no network calls to arbitrary hosts. The capability list is the agent's entire footprint, checked at compile time.

Credentials don't belong in the code

In a conventional agent framework, the agent reaches for its own API key:

import anthropic, os

client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

response = client.messages.create(
    model="claude-opus-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": prompt}]
)

The key is in an environment variable, readable by any code in the process. If a prompt injection tricks the agent into calling a different endpoint or exfiltrating os.environ, nothing stops it. The security boundary is a naming convention.

In Qosm, the API key lives in the host. It provisions model before the agent code runs. The agent calls a typed function and can never see or forward the credential. It doesn't exist in the agent's scope.

Capabilities are functions

That's the core idea. Since a capability is a function, you can narrow it before handing it to an agent:

attenuate.qosmQosm
Provided by host
extern read_file : {path: String} -> String ! {File.Read};
Agent code
// Attenuate: restrict to a single directory.
let config_read path = read_file {path: "/config/" ++ path};

// Attenuate further: a single file, no arguments.
let app_config _ = read_file {path: "/config/app.toml"};

// The agent receives app_config.
// It cannot read anything else. Not by cleverness,
// not by prompt injection — by construction.

The host doesn't just decide which capabilities to grant. It can scope them down before handing them off. No policy engine, no middleware. Just closures.

When capabilities compose, the types say so

compose.qosmQosm
Provided by host
extern db_insert : {key: String, value: String} -> Unit ! {Db.Insert};
Agent code
let classify text =
  model @{category: String, confidence: Float}
  `Classify this text: {{ text }}`;

let store label data =
  db_insert {key: label, value: toString data};

let classify_and_store text =
  match classify text with (
  | Ok r -> store (.category r) r
  | Err e -> store "error" e);

// Uses two capabilities: model and db_insert.
// The type tracks both. No surprises.

classify_and_store has type String -> Unit ! {LLM.Call, Db.Insert}. The effect set is the full capability footprint of the program. The host can read it before anything runs. When capabilities compose, their effects merge. Nothing is hidden.

MCP tools become typed functions automatically

Connect a GitHub or Slack MCP server and every tool gets a generated typed signature:

generated preludeQosm
// Auto-generated from connected MCP servers

extern create_issue  : {repo: String, title: String, body: String}
                    -> {number: Int, url: String} ! {GitHub};

extern search_repos  : {query: String, limit: Int}
                    -> Array<{name: String, stars: Int, url: String}> ! {GitHub};

extern send_message  : {channel: String, text: String}
                    -> {ts: String} ! {Slack};

extern query         : {sql: String, params: Array<String>}
                    -> Array<{row: {col: String, val: String}}> ! {PostgreSQL};

extern create_charge : {amount: Int, currency: String, customer: String}
                    -> {id: String, status: String} ! {Stripe};

extern web_search    : {query: String}
                    -> Array<{title: String, url: String, snippet: String}> ! {Linkup};

If the agent tries to call something that wasn't granted, or passes the wrong argument shape, the compiler rejects it. The effect annotations propagate through the whole program. If your function calls create_issue, its type says so.

Built to be written by models

Qosm is not an IDE. You write it with Claude Code, Codex, Cursor, or whatever you already use. The language is small by design. It takes less than 1k tokens to teach a model how to write valid Qosm. The type system catches mistakes before they run.

Agents are already writing production code. The question is whether we have the right tools to trust it. Type systems, effect tracking, and capability boundaries are not new ideas. Applying them to a world where the author is a model is.

Qosm is live in private beta. If you want to be an early customer, reach out to Pierre on LinkedIn.