v0.1 — now open source

Pipethon

Flow  ·  Match  ·  Think

A modern programming language built for the age of intelligent systems — designed around pipeline composition and pattern matching.

See examples View on GitHub

The language

Why we built Pipethon.

Pipethon was born out of frustration with the complexity of building AI-powered applications in traditional languages. When working with large language models and data transformation pipelines, developers face deeply nested callbacks, brittle string parsing, and unpredictable output. Pipethon was designed to solve all three at once. By centering the language around two core primitives, pipeline composition and pattern matching, Pipethon turns what used to be messy, hard-to-read code into clear, expressive programs that tell a story from input to output.

In Pipethon, every program is a series of transformations. Data flows through stages using the |> operator, where each stage receives the output of the last, reshapes it, routes it, or passes it along. This pipeline-first design eliminates the tangled control flow that plagues most AI application code and makes programs dramatically easier to read, test, and maintain. There are no deeply nested conditionals, no fragile string manipulation. Just clean, readable pipelines.

At every stage, Pipethon's pattern matching lets you describe what your data looks like and what should happen to it by type, by shape, by value, or by structure. When an AI model returns unpredictable output, pattern matching tames it. When a pipeline needs to branch based on confidence scores or intent classification, pattern matching routes it elegantly. Pipethon is not just a language for writing AI apps, it's a language that thinks the way AI pipelines actually work.

Why Pipethon

Built different,
by design.

Pipeline composition

Every program is a series of clean transformations. Data flows stage to stage, no tangled callbacks and no deeply nested conditionals.

Pattern matching

Match by type, shape, value, or structure. Tame unpredictable AI output, route branches cleanly, and validate data with elegance.

AI-native primitives

Pipethon is designed from the ground up to integrate with AI models. Call, classify, and branch on model output in a single pipeline.

Examples

The language in action.

hello_world.pipe
let + pipeline operator
// Example 1: Hello World — a let binding piped to print
let greeting = "Hello, World!" |> print;
grade_checker.pipe
pattern matching + guards
// Example 2: Pattern matching on scores with if-guards
let score: Int = 85n;

score |> {
  int(n) if n >= 90n => "A"
  int(n) if n >= 80n => "B"
  int(n) if n >= 70n => "C"
  int(n) if n >= 60n => "D"
  _                  => "F"
} |> print;  // prints "B"
type_dispatch.pipe
type matching + named pipeline
// Example 3: Dispatching on runtime type using typePat patterns
pipeline describe: Any -> Any = 42n |> {
  int(v)    => "It's an integer"
  float(v)  => "It's a float"
  string(v) => "It's a string"
  list(v)   => "It's a list"
  bool(v)   => "It's a boolean"
  _         => "Unknown type"
};

42n           |> describe |> print;  // "It's an integer"
"pipethon"    |> describe |> print;  // "It's a string"
[1n, 2n, 3n] |> describe |> print;  // "It's a list"
null_coalesce.pipe
optionals + ?? + some/none
// Example 4: Optional types, some/none patterns, and ?? coalescing
let username: String? = none;
let display: String?  = "Alice";

// ?? falls back to the right-hand value if the left is none
username ?? "guest" |> print;  // "guest"
display  ?? "guest" |> print;  // "Alice"

// exhaustive some/none pattern matching
username |> {
  some(name) => name
  none       => "Hello, stranger"
} |> print;  // "Hello, stranger"
ai_query_handler.pipe
llm() + pattern matching + pipelines
// Example 5: Full AI pipeline — llm() stage, pattern match, null coalesce
let query: String = "What is Pipethon?";

query
  |> llm(model: "claude", prompt: "Classify as question/task/other: {input}")
  |> {
       some(label) if label == "question" => "I'll answer that!"
       some(label) if label == "task"     => "On it."
       some(label)                          => label
       none                                 => "unknown"
     }
  |> print;

Static analysis

13 rules, enforced at compile time.

Pipethon enforces 13 static constraints at analysis time. Violations are reported with precise source locations.

01

none can only be assigned to a variable declared with an explicit optional type (?).

02

The source of a ?? expression must be typed as optional.

03

The left operand of ?? must be an optional type.

04

llm() calls must include a model argument.

05

llm() calls must include a prompt argument.

06

Pattern blocks must be exhaustive — must include a wildcard _ or cover all cases.

07

The wildcard _ arm must be the last arm in a pattern block.

08

Guard conditions must be boolean expressions.

09

Type annotations in let and pipeline declarations must name known types.

10

Object patterns must not repeat the same field name.

11

Variables must be declared before use.

12

No two declarations in the same scope may share a name.

13

drop may only appear as an arm body inside filter, map, or each stages.

The team

Built by three.

Elias Segura

Elias Segura

Co-creator

LMU Full-Stack CS grad with a passion for programming languages, frontend design,and AI. Focused on language design and implementation, with an interest in how programming languages can evolve to meet the needs of AI-driven development.

Garnik Gevorkyan

Garnik Gevorkyan

Co-creator

Co-Creator of Pipethon. Focused on analyzer and compiler design of the language. LMU CS graduate with a passion for ML and GenAi pipeline construction and design.

Riley Vegting

Riley Vegting

Co-creator

The GOAT of the team. TypeScript enthusiast. Cracked at coding. LMU grad studymaxxing game and software development. Some say he has too much aura.