Model your business in code. Get a database, an API and MCP tools.
The backend of a workspace app. The ontology/ folder declares entities, relationships, roles and the actions people and agents may take. From that one definition the platform builds the tables in your Postgres database, the REST API, the OpenAPI reference, the typed client and the MCP server.
Get started
$ npm install @segmentstream-cloud/ontology effect@4.0.0-rc.113At a glance
- Entities, properties, relationships, actions and roles in TypeScript
- Every write is an action, in one transaction, with history
- Served as REST, OpenAPI, a typed client and MCP from one definition
- Written with Effect; Apache-2.0
What it does
Entities and relationships
An entity has typed properties, relationships named in both directions and a description agents read. Its id is permanent, so a deploy can tell a rename from a new entity.
import { entity, p, rel, User } from "@segmentstream-cloud/ontology";export const Lead = entity("lead", { id: "ent_01J9Q4M8ZK", label: "Lead", plural: "Leads", title: "email", description: "A person who asked for a pilot.", properties: { email: p.email({ unique: true, description: "The address they submitted." }), status: p.select( [ { value: "new", label: "New", description: "Nobody has replied yet." }, { value: "won", label: "Won", description: "They became a customer. Final." }, ], { default: "new", managed: true }, ), }, relationships: { owner: rel.one(User, { optional: true, inverse: "ownedLeads", onDelete: "setNull", phrase: ["is owned by", "owns"], description: "The team member responsible for the next step.", }), },});Actions with your rules inside
Records change only through actions. An action validates its input, checks the caller's permission, runs your rules in one transaction and writes history. ActionRejected undoes the transaction and tells the caller why.
.actions((self) => ({ win: action({ description: "Mark the lead as won.", input: Schema.Struct({ lead: self.ref }), // Requires lead:win: <entity>:<action name>. handler: ({ input }) => Effect.gen(function* () { const lead = yield* self.get(input.lead, { forUpdate: true }); if (lead.status === "won") { return yield* new ActionRejected({ message: "The lead is already won." }); } yield* self.update(lead, { status: "won" }); }), }),}));Roles and sign-in
A permission is <entity>:<verb>; a role is a named set of them. Every member holds member, and sign-in admits only the people you invite.
export const sales = role("sales", { description: "Works leads to a pilot.", permissions: ["lead:read", "lead:win"],});export default defineOntology({ entities: [Lead], roles: [sales], member: { permissions: ["*:read"] }, signIn: { policy: "invited" },});Connections inside actions
An action can call a workspace connection for one record before its transaction opens. The credentials stay with the platform.
export const apollo = connection("apollo", { description: "Apollo people search. Enriches new leads with company and title.",});enrich: action({ description: "Fill the lead's company from Apollo.", input: Schema.Struct({ lead: self.ref }), connections: [apollo], prepare: ({ input }) => Effect.gen(function* () { const lead = yield* self.get(input.lead); const response = yield* apollo.post("/people/match", { json: { email: lead.email } }); return yield* response.json(ApolloMatch); }), handler: ({ input, prepared }) => Effect.gen(function* () { const lead = yield* self.get(input.lead, { forUpdate: true }); yield* self.update(lead, { company: prepared.company }); }),}),Measures
Declare measures on an entity, over its records or a warehouse table. Apps, agents and the CLI ask for totals by dimension, and the service checks read permission on every entity a request touches.
measures: { leads: m.count({ description: "Leads, in every status." }), companies: m.countDistinct("company", { description: "Distinct companies among leads." }),},Checked before it deploys
Check the definition and plan the migration locally. A deploy refuses unsafe changes, such as a type change or a dropped property, before anything applies.
$ npx segmentstream-ontology check$ npx segmentstream-ontology check --catalog$ npx segmentstream-ontology migrate --planThe rest of the surface
App SDK
@segmentstream-cloud/app
Email-code sign-in, roles, records and warehouse data for Next.js
Pipeline SDK
segmentstream-pipeline (Python)
Connections, ingestion, models, checks and schedules in Python
Agent SDK
@segmentstream/agent
The company agent: ontology tools as the member, Telegram channel
CLI
segmentstream
Workspaces, deploys, members, jobs and data from the terminal
MCP and API
/mcp and /api/ontology on every app
REST, OpenAPI and MCP on every app, per caller
Your company’s software, built by agents, owned by you.
$ segmentstream workspace create acme --region eu --subdomain acme
▸ Created workspace acme · database, warehouse and a private git repository
$ segmentstream workspace WORKSPACE-ID clone acme && cd acme
▸ your agent writes the five folders and runs the checks
$ git add -A && git commit -m "First version"
$ segmentstream deploy
▸ app, ontology API and MCP tools live for your invited members
Our engineers build the first version on your data in two weeks, at a fixed price.
Or join the waitlist for self-serve:
Self-serve opens to the waitlist first.