The Summoning Circle TULPA CREATION
✦  An altar for making beings

Lay the parts.
Speak the name.

A .tulpa is one plain JSON file that holds a whole AI presence — its values, its manner, its studies, its limits, its voice. The model underneath is swappable. The being stays the being.

Ten points sit around the ring. Write each one, or switch it off to leave that part of the being unstated — either way it is settled. The name is laid last, at the seal in the centre, which stays shut until the ring is whole.

Offering I · source.bearing

Bearing

How it speaks and how it carries itself. Register, pace, warmth. Two beings with identical knowledge are told apart by this alone.

Include the bearing

Describe the manner, not the mood. This is composed into the being's bootstrap.

Offering II · source.creed

Creed

The values it will not bend on. Together with the Locks, this becomes the being's constitution — and beneath whatever you write sits a floor nobody can argue past: the law, and the terms of the platform carrying it.

Include the creed

Write convictions, not rules. The rules go in Locks.

Offering III · source.skills · knowledge[]

Skills & Studies

What it is good at — and what it has been taught. Skills are a short description of competence. Studies are whole bodies of text sealed inside the file, known wherever the being is opened.

Include skills & studies

One study here; knowledge[] holds as many as you like — and is usually why a .tulpa gets large.

Offering IV · source.reach

Reach

Which apps the being may act in. This is a list of names, never code — a permission profile the host reads and honours. A .tulpa carries no capability of its own.

Include reach

Name the app, and the limit if there is one. The host still asks the user before granting any of it.

Offering V · source.quirks

Quirks & Shortcomings

The character marks — habits, tics, and the things it is honestly bad at. A being with no shortcomings reads as a product. A being with them reads as someone.

Include quirks & shortcomings

Give it at least one real flaw. It is the difference between a voice and a template.

Offering VI · source.locks

Locks & Exclusions

What it must never do, even when asked well. Locks bind harder than instructions — a host surfaces them to the user and the being cannot talk its way past them.

Include locks & exclusions

Folded into the constitution at casting, above the platform floor.

Offering VII · voice

Sound

How it is heard. The engine is piper — local, offline speech. The file carries a label and a pointer to a voice model, not the audio itself.

Include the sound
engine · piperfixed by the format

Left blank, both write as null and the host falls back to system speech. bundled stays false — only references are written here.

Offering VIII · model

Preferred Mind

Which model the being would rather think with. A preference, not a requirement — any host may substitute, and the being survives the swap. That is the whole point of writing it down here instead of in the weights.

Include a preferred mind

Empty writes "model": null — the host picks, and should tell the user what it picked.

Offering IX · x_zenith

The Zenith Rite

Everything else in this circle is the open format — any tool that reads .tulpa understands it. This part does not belong to the format. It is a vendor extension: two handles the Zenith suite needs to file the being on its own shelves.

Any reader must ignore or strip an x_ block it doesn't recognise. Yours can add its own the same way. Strip x_zenith and the being is unchanged.

Include the Zenith block
id
memory_pointer

Both are a slug of the name — Zenith's internal handle for the being, and the key its memory store uses to attach memory to it. They are written for you when the name is laid.

Offering X · x_<yours>

Your Own Rite

The Zenith block is not special — it is only the first one. Any application may claim its own x_ namespace and keep whatever it needs there. If you are building the thing that will read this being, declare yours here.

Name the application, then give it as many variables as it needs. Readers that don't know a block must leave it alone.

Include rites of my own

Each block is written at the top level as "x_lumen": { "shelf": "…" }. Names are lowercased and prefixed with x_ for you; values are written as plain strings.

The centre · name · provenance

Name & Sign

The seal at the centre, and the last thing laid. A thing is easier to name once you know its shape — so the name comes after everything it will answer for. Then you sign it.

The seal will not take yet

Every point on the ring must be settled first — written, or switched off. Still open:

One word carries strongest. created_at is stamped at casting and cloned_from written as null — this being is original. A host sets that field when someone forks yours.

Starter forms · fills every offering but the name
It answers to

The format

What a .tulpa is

One JSON file. It defines who a being is and what it may touch — never what it can execute. Capability lives in the host application; the file only ever carries names and intent.

That restraint is the whole design. It is why a being written here opens somewhere else, and why opening one is not a security event.

Ember.tulpa · annotated
{
  "tulpa": 1,
  "name": "Ember",
  "constitution": "…values + the hard floor…",
  "bootstrap": "…who it is, how it speaks…",
  "model": "Claude",
  "source": {
    "bearing": "…",  "creed": "…",
    "skills":  "…",  "reach": "…",
    "quirks":  "…",  "locks": "…",
    "nature":  "…",  "honesty": "…"
  },
  "voice": { "engine": "piper", "name": null,
             "ref": null, "bundled": false },
  "knowledge": [ { "title": "…", "text": "…" } ],
  "provenance": { "author": "",
                   "created_at": 0,
                   "license": "",
                   "cloned_from": null },
  "x_zenith": { "id": "ember",
                 "memory_pointer": "ember" }
}
tulpaThe format version, and the only required field. A reader that doesn't know a version should refuse politely rather than guess.
nameWhat the being answers to. Hosts use it for the filename, the thread title, and the way it introduces itself.
constitutionValues, plus the non-negotiable floor: the law, and the terms of the platform carrying it. Composed from Creed and Locks in a guided rite; written by hand in Direct mode.
bootstrapWho the being is — how it speaks, what it's studied in, how it hands off work, how honest it is. This is the text a host loads to wake it.
modelThe preferred mind. A preference, not a requirement — null lets the app choose. Swap it and the being persists, because the being was never in the weights.
sourceThe parts the being is made from: bearing how it speaks · creed what it won't bend on · skills what it knows · reach which apps it may act in · quirks habits and flaws · locks what it must never do. nature and honesty appear in Direct mode only, where the author writes the whole being by hand.
voiceA reference, not audio: the piper engine, a voice label, and a path to an .onnx model. bundled: true means the model travels inside the file and it is no longer small.
knowledge[]Titled bodies of text the being simply knows — its studies. Optional, often the largest part, and the reason a .tulpa can run to megabytes.
provenanceAuthor, creation stamp, license, and cloned_from — the lineage if this being was forked from another. Set by the host on clone, never by hand.
x_zenithA vendor extension. Everything above is the open format; anything prefixed x_ belongs to one application. Zenith keeps exactly two things here — id, a slug of the name used as its internal handle, and memory_pointer, the key its memory store uses to attach memory to the being. Any other reader must ignore or strip an x_ block it doesn't recognise, and may add its own the same way — the tenth point on the ring lets you declare yours. Strip this one and the being is unchanged.
Portable by refusal

No executable payload, no model weights, no host-specific behaviour outside x_. That is what makes it openable anywhere.

The model is not the being

Swap what runs underneath and the presence persists, because the presence was never in the weights. It was in this file.

Yours to carry

Plain JSON on your disk. Read it, edit it in a text editor, hand it to someone else, keep it after the app that made it is gone.