Introducing PROMPTRAN — an un-intelligent orchestration language with just two-and-a-half statements.
Figure 0 (left) — the official PROMPTRAN language badge (also available for PLANKALKÜL).
We introduce PROMPTRAN, a simplistic
programming paradigm for orchestrating modern “AI” agents. Observing the
mischief acceptance of undefined priors can cause—logically, culturally
and in commerce—we attempt to minimize blind dependence on
“intelligence” (whatever it is) in our programming language. As a result
this presentation is a bit of a shaggy dog story—it makes a big to-do,
teasing a whole new language, only in the end to deliver merely
two-and-a-half statement types.
Back in the day—when men were men, Grace Hopper was not yet an
Admiral (and mice were vermin, not fondled peripherals)—computer
programming started strong, via virilely named languages like
PLANKALKÜL (Zuse c. 1945),
ENIAC 60-ORDER CODE (von Neumann,
Clippinger & friends c. 1948),
BRIEF CODE (Mauchly et al. c.
1949), A-0 (Hopper & others
c. 1951), FORTRAN (Backus &
others c. 1954), IPL (Newell et
al. c. 1956), APL (Iverson c.
1957), ALGOL (Perlis et al.
including McCarthy c. 1958), and
COBOL (Hopper & others c.
1959).
Then John McCarthy went and messed everything up, inventing both
Artificial Intelligence and LISP
(and also promulgating timesharing)!
Heroic efforts to turn the tide were made, with
JCL (IBM c. 1964),
BASIC (Kemeny & Kurtz c.
1964), TRAC (Mooers & Deutsch
c. 1964), FORTH (Moore &
friends c. 1968), and PLANNER
(Hewitt c. 1969). However as the 1970s dawned, and despite a
vigorous rally by CONNIVER (Sussman &
McDermott c. 1972), and, most notably,
INTERCAL (Woods & others c.
1972), the industry rode off into the twilit sunset
notwithstanding Smalltalk (Kay &
friends c. 1972), ACTOR (Hewitt
& others c. 1972), SCHEME
(Sussman & Steele c. 1975) and their modern progeny, along
with the valiant WEB (Knuth c.
1979). Alas, COMMON LISP (Steele,
Fahlman, Gabriel, Moon, Weinreb & others c. 1984) was
overlong aborning, becoming an ANSI standard too late to avert the dark
ages of the AI winter.
Now, deep into the following century, when “worst is better”,
bestriding the challenge of orchestrating the awesome powers of modern
agentic “AI” systems, PROMPTRAN modestly
attempts to once again mount these giant shoulders.
This PROMPTRAN paradigm originated as a
small spin-off from our cultivated computing mission—breeding
individualized software environments whose affordances
compound over time. Such systems like to organize themselves around
activities rather than around tools or assets, and assimilate
the technologies they incorporate—agentic workers included—rather than
emphasizing them.
The aim, when orchestrating agents, is to have them interoperate
seamlessly with both agentic and non-agentic automation
resources, in a vendor-agnostic, scalable way. We observe as an industry
trend that too many “AI” products claim a surfeit of “intelligence”.
Thus a goal of PROMPTRAN—along with
facilitating the construction of complex agentic systems—is to make
intelligence optional—a component plugged into a simple-minded
foundation.
Our setting is a world of entities; we focus on their aspect as actors. Concretely, an entity is just the folder of files and folders that describe it; nothing about it lives anywhere else. The actor aspect is activated—woken from a passive state—by the system applying an animator to a brief—that is, applying a procedure to a program-description, applying an interpreter to a text. The brief is a textual dataset assembled on demand from the entity’s files. Demystified fully: the events being orchestrated in the system are simply processes being launched and fed some data.
Agents enter this setting as programs, no differently from any other
software with a non-agentic (eg Python) animator. For instance an
Anthropic Claude Code animator is implemented as the functional
equivalent of a shell call of the form claude -p ...—where
the ellipsis is a reference to the above-mentioned brief, which acts as
a prompt to the agent. These briefs, or prompts, are assembled
by the PROMPTRAN system and interpreted by
the animator. Note that the brief does not comprise the only data
available. The actor may also access other system resources and effect
changes just like any other program.
In addition, all entities are provided with message-passing capabilities, and the system thereby operates in the style of Hewitt’s Actor Formalism. Our actors get activated when they have messages to process—control and data flows can be implemented by sending entities messages with content suitably formatted for their animators’ interpretation. Each entity keeps a queue of incoming messages (its hopper); an activation takes the oldest one and folds it into the brief, so the animator can read the entity’s standing description and the thing it was just asked to do as one text. An activation’s outputs are effects: files written, messages sent.
Figure 1 — the heartbeat: a message arrives in the entity’s queue (the hopper), the entity is activated, animated, and returns to rest.
message ┌─────────┐ ┌──────────────┐ ┌───────────┐
──────────────────────►│ hopper │──►│ assemble the │──►│ animator │
(a DO, from anyone) │ (FIFO) │ │ brief │ │ │
└─────────┘ │ its files │ │ agent / │
│ + method │ │ Python / │
│ + message │ │ human … │
└──────────────┘ └─────┬─────┘
│
┌──────────────────────────────────────┘
▼
effects: files written; messages deposited in
other entities' hoppers (a HAVE, a continuation) …
then the entity is passive until its next message.
We materialize the system’s native artifacts in a stylized Markdown
dialect. The dialect’s emphasis is machinability rather than
presentation. However it’s close enough to most standards (such as
CommonMark) that PROMPTRAN artifacts are
ordinary .md files that “just work” in
most any tool. The divergences only appear at the extremes (such as
subsections at depths above “H6”) which rarely is a practical issue.
We view the markdown medium as being comprised primarily of blocks of content called facets, which are preceded by a heading referred to as the title of the facet. By default, content is assumed to be free text, thereby readily accommodating natural language (NL) material such as agent prompts. However the content may also contain (or even entirely consist of) insets of “unnatural language”—formalisms (such as Python, JSON etc)—that are set off and type-annotated in the usual markdown way by using “backtick fencing”.
This polyglot medium makes the paradigm language-agnostic, because the animator chooses what to read. An agentic animator takes the natural language as its directions and may treat any insets as clarification. In contrast a Pythonic animator runs the insets and treats the prose as comments. The system thus offers a portfolio of interpreters for a single program text. For example we can trade flexibility of expression for deterministic precision by swapping out the agentic animator for a traditional programming engine.
One useful development process this enables is to start with NL descriptions, animated by agents, to reach a proof of concept—then to replace NL with code incrementally, inset by inset. The prose that remains rides along as an integrated specification. Swapping animators is a conformance test, and a production entity running only its code insets still carries its own documentation—realizing Knuth’s Literate Programming vision by an organic route.
PROMPTRAN LanguageThe system treats facets that describe units of behavior like method definitions. The title of the facet is interpreted by the system like a signature.
Argument bindings provided in the message are then substituted for
parameters in the method definition (as in many applicative functional
languages). We use moustache syntax—the spelling a nod to the
modern partiality for mice: parameters are indicated by surrounding
their name symbols with double curly braces—for example
{{foo_bar}}.
These patterns are then used to author the
PROMPTRAN statement types:
To defines a method,
Do invokes one, and
Have asks another entity to.
To StatementA To statement defines one method. Its
first line is the facet’s title—the signature—and the facet’s body
describes what the entity does to perform that method. The syntax is
To <method-name> with <parameter-names>* ...
where the ellipsis stands for the body, for example
To greet with name, greeting
Include "Hello, {{name}}! {{greeting}}" in your response.
would be a simple method definition used with an agentic animator. You could also replace (or accompany) the NL with a Python block
```python
print("Hello, {{name}}! {{greeting}}")
```
Do StatementThe Do statement is used to perform the
actions specified by To statements. The
actions of entities are orchestrated by sending them
Do statements as messages.
When a Do message arrives, the entity
is activated: the system matches the message against the entity’s
signatures, includes the matching method in the brief with the arguments
substituted for its parameters, and hands the result to the animator.
The syntactic pattern is
Do <method-name> with <argument-bindings>,
for example
Do vibe-code with product-name=FooGame, spec=`product/specs/foo.md`
Do play-test with product-name=FooGame, object=`artifacts/foo.py`
Do triggers an entity’s pre-defined
behaviors, which have been factored into actions via
To statements (basically like “tools” or
“skills”, but with no agentic presumptions). These can thus be
individually called selectively, sequenced, incorporated with other
behaviors and so on.
The control flow semantics of Do is
effectively like a “goto” augmented with parameter binding:
control is handed over, and nothing comes back to the sender.
Have StatementThe Have statement simply extends the
Do statement with a small prefix naming an
entity. The syntax is
Have <entity> do <method-name> with <argument-bindings>.
(Alternatively, one could view Do as a
simplification of Have, where the entity
parameter is always implicitly bound to “self”.)
Where Do is a “goto”,
Have is a “function call”:
control initially goes to the callee, but when the callee finishes,
control comes back—not to the start of the method, but to the line after
the Have. The underlying device is a
continuation: a deferred
Do, passed to the callee with the
call, which the callee then sends back to the caller when it is
done.
To accomplish this the system factors each method into a sequence of
component methods that each begin at the lines following a
Have statement. These continuation
points are labeled internally with sequential names of the form
<method-name>+<N>, with
<N> increasing from
1.
For example suppose the entity Foo contains the
following:
To frotz with ...
XXX
Have Bar do mumble with ...
YYY
Internally this single method gets refactored into the following two methods:
To frotz with ...
XXX
Have Bar do mumble with ...
To frotz+1 with ...
YYY
Then the continuation passed to Bar by the
Have statement is equivalent to a deferred
directive to Bar to send Foo a
message saying Do frotz+1 .... This deferred
directive is to be executed after Bar finishes
executing the mumble method. The callee’s exit status and
its reply also ride along with the continuation, bound as
{{status}} and {{reply}}.
Figure 2 — a Have execution: the
call goes out with the rest of the method riding along; the callee’s
return comes back as a message.
Foo Bar
─── ───
DO frotz ...
│
├─ XXX
│
├─ HAVE Bar DO mumble ... ───────────► hopper: "DO mumble ...
│ (the rest of frotz, then send Foo
│ now named frotz+1, DO frotz+1 ... status, reply"
│ rides along as the │
│ continuation) ├─ mumble runs
│ │
passive ▼
│ Bar returns; the system
hopper: "DO frotz+1 ... status, reply" ◄── performs the continuation
│
DO frotz+1 ...
│
└─ YYY
This pattern is a familiar one in actor-based programming systems. We
adopt it here to implement the two-and-a-half
PROMPTRAN primitives needed to deliver
orchestration, not just for agents, but any automation.
Linguistically, Have is a
Do with a small prefix tacked on.
Functionally, Do is a
Have with the continuation machinery
removed. They are neither two distinct statements nor just one.
Splitting the difference, and adding in
To, justifies
PROMPTRAN’s modest claim to having only
two-and-a-half statements.
A new, vastly over-produced,
PROMPTRAN II.V iteration is rumored to be
in the pipeline, but no details or release has been shared. Nonetheless,
along with our doughty user community, we look forward to stepping into
a glorious future!
PLANKALKÜL — Konrad Zuse, “Über den allgemeinen Plankalkül als Mittel zur Formulierung schematisch-kombinativer Aufgaben,” 1948. (The Plankalkül itself was developed principally during 1942–1945.)
ENIAC 60-ORDER CODE — R. F. Clippinger, A Logical Coding Scheme Applied to the ENIAC, Ballistic Research Laboratories Report No. 673, Aberdeen Proving Ground, Maryland, September 1948. See also Herman H. Goldstine and John von Neumann, Planning and Coding of Problems for an Electronic Computing Instrument, Institute for Advanced Study, 1947–1948.
BRIEF CODE — John W. Mauchly, “Short-Order Code,” unpublished notes and work at the Eckert-Mauchly Computer Corporation, c. 1949. See also Grace Murray Hopper, “The Education of a Computer,” Proceedings of the 1952 ACM National Meeting (Pittsburgh), 1952, pp. 243–249, which credits Mauchly with the basic principles of the “short-order code.”
A-0 — Grace Murray Hopper, “The Education of a Computer,” Proceedings of the 1952 ACM National Meeting (Pittsburgh), 1952, pp. 243–249.
FORTRAN — John W. Backus, R. J. Beeber, Sheldon Best, Richard Goldberg, Lois M. Haibt, Harlan L. Herrick, Robert A. Nelson, David Sayre, Peter B. Sheridan, Harold Stern, Irving Ziller, Robert A. Hughes, and Roy Nutt, “The FORTRAN Automatic Coding System,” Proceedings of the Western Joint Computer Conference, Los Angeles, February 1957, pp. 188–198.
IPL — Allen Newell and Fred M. Tonge, “An Introduction to Information Processing Language V,” Communications of the ACM 3(4), April 1960, pp. 205–211. (IPL originated in the work of Newell, J. C. Shaw, and Herbert A. Simon beginning c. 1956.)
APL — Kenneth E. Iverson, A Programming Language, New York: John Wiley & Sons, 1962. (Iverson’s notation was developed during the preceding several years.)
ALGOL — J. W. Backus, F. L. Bauer, J. Green, C. Katz, J. McCarthy, P. Naur, A. J. Perlis, H. Rutishauser, K. Samelson, B. Vauquois, J. H. Wegstein, A. van Wijngaarden, and M. Woodger, “Report on the Algorithmic Language ALGOL 60,” Communications of the ACM 3(5), May 1960, pp. 299–314. (The language grew from the International Algebraic Language defined at the 1958 Zürich conference.)
COBOL — CODASYL, COBOL: Initial Specifications for a Common Business Oriented Language, U.S. Department of Defense, April 1960. (COBOL was designed during 1959; Grace Hopper participated in the CODASYL effort, and her earlier FLOW-MATIC was an important precursor.)
ARTIFICIAL INTELLIGENCE — John McCarthy, Marvin L. Minsky, Nathaniel Rochester, and Claude E. Shannon, A Proposal for the Dartmouth Summer Research Project on Artificial Intelligence, August 31, 1955. (The proposed workshop was held at Dartmouth in the summer of 1956.)
LISP — John McCarthy, “Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I,” Communications of the ACM 3(4), April 1960, pp. 184–195. (LISP development began at MIT c. 1958; an earlier version of this paper appeared as MIT AI Memo 8, March 1959.)
TIMESHARING — John McCarthy, “A Time Sharing Operator Program for Our Projected IBM 709,” memorandum, MIT Computation Center, January 1959. (McCarthy was among the earliest and most influential promulgators of general-purpose interactive time-sharing.)
JCL — IBM, IBM System/360 Operating System: Job Control Language, IBM Systems Reference Library, 1960s. (System/360 was announced in 1964 and its OS/360 Job Control Language became the archetypal JCL.)
BASIC — John G. Kemeny and Thomas E. Kurtz, BASIC: A Manual for BASIC, the Elementary Algebraic Language Designed for Use with the Dartmouth Time Sharing System, Dartmouth College Computation Center, Hanover, New Hampshire, 1964. (The first BASIC programs ran on May 1, 1964.)
TRAC — Calvin N. Mooers and L. Peter Deutsch, “TRAC, A Text Handling Language,” Proceedings of the 20th National Conference of the ACM, 1965. See also Calvin N. Mooers, “TRAC, A Procedure-Describing Language for the Reactive Typewriter,” Communications of the ACM 9(3), March 1966.
FORTH — Charles H. Moore, Programming a Problem-Oriented Language, unpublished manuscript, c. 1970. (Moore’s development of the system that became FORTH began during the 1960s; the name FORTH dates from c. 1968.)
PLANNER — Carl Hewitt, “PLANNER: A Language for Proving Theorems in Robots,” Proceedings of the First International Joint Conference on Artificial Intelligence (IJCAI), Washington, D.C., 1969, pp. 295–301.
CONNIVER — Gerald Jay Sussman and Drew Vincent McDermott, Why Conniving Is Better than Planning, MIT Artificial Intelligence Laboratory Memo 255A, Cambridge, Massachusetts, April 1972. See also Sussman and McDermott, “From PLANNER to CONNIVER—A Genetic Approach,” Proceedings of the 1972 Fall Joint Computer Conference, 1972, pp. 1171–1179.
INTERCAL — Donald R. Woods and James M. Lyon, The INTERCAL-72 Programmer’s Manual, Princeton University, 1972.
Smalltalk — Alan C. Kay, “The Early History of Smalltalk,” ACM SIGPLAN Notices 28(3), March 1993, pp. 69–95. (The first version, Smalltalk-72, was developed at Xerox PARC in 1972.)
ACTOR — Carl Hewitt, Peter Bishop, and Richard Steiger, “A Universal Modular ACTOR Formalism for Artificial Intelligence,” Proceedings of the Third International Joint Conference on Artificial Intelligence (IJCAI), Stanford, California, 1973, pp. 235–245. (The work originated in the MIT AI Laboratory c. 1972.)
SCHEME — Gerald Jay Sussman and Guy L. Steele Jr., Scheme: An Interpreter for Extended Lambda Calculus, MIT AI Memo 349, Cambridge, Massachusetts, December 1975. (It originated as an exploration of Hewitt’s actors; everything proved to be ultimately lambda.)
WEB — Donald E. Knuth, “Literate Programming,” The Computer Journal 27(2), 1984, pp. 97–111. (Knuth began designing WEB in spring 1979 as a prototype called DOC, and cast it into its recognizable WEB form in 1981.)
COMMON LISP — Guy L. Steele Jr., Common Lisp: The Language, Burlington, Massachusetts: Digital Press, 1984. (Design began in 1981 but the X3J13 committee’s spec only became ANSI standard X3.226 at the end of 1994.)
The arguably human author (as attested by countless CAPTCHAs) claims sole responsibility for this content and prose, but wishes to thank OpenAI, ChatGPT (GPT-5.6 Sol), for reference-desk, bibliographic birddogging and poofreading assistance.
The PROMPTRAN development team also
appreciates the many contributions of “GW”, a persistent agentic actor
defined in our system, named in honor of George Weil, who
withdrew the control rod from the Manhattan Project’s experimental
atomic pile, initiating the first human-prompted nuclear chain reaction
on December 2, 1942, “precisely” at 3:25 p.m. Chicago time. Usually
animated by Claude Cowork, with Anthropic’s Fable and Opus models, GW
notably introduced the +<N> notation
used to label continuations. In dogfooding our
PROMPTRAN-defined dev workflows we often
happily just “Have George Do {{it}}”.
—Marc LeBrun. Copyright Prometheus Sherpas, LLC, September 2026. CC-BY-SA-4.0
PROMPTRAN CodeHere’s a sample of real PROMPTRAN code,
vibe-coded by agents, for orchestrating part of our actual sprint
process, taken from a snapshot of work-in-progress.
It exemplifies “literate”
PROMPTRAN—the natural language segments
can either directly prompt an agent, or the Python insets can be
directly executed by a non-agentic code animator. An agentic animator
can ignore the code, or take it as a clarifying supplement to the NL.
Likewise a Pythonic animator can ignore the prompts, or treat them as
comments. This of course can generalize to support more complex polyglot
artifacts, for any value of poly.
Note that the Have and
Do lines belong to neither natural
language nor Python, but to PROMPTRAN.
They are the orchestration statements, performed by the system itself,
regardless of which animator runs the segment—so the animators may
ignore each other’s material without breaking control flow.
Figure 3 — The dev process this sample implements: one work
order, four participants (the activity and the three entities its
config.md casts), and two human decisions.
director sprint-orders (the activity) planner builder
──────── ──────────────────────────── ─────── ───────
── DO open ───► open {{order}}
│ phase: drafting
├── HAVE planner DO draft ─────────► drafts
│◄─────────────────── status, reply ──┘
│ phase: issuing
◄── "please issue" ┤
decides │ (a human decision: it arrives
── DO issued ─────►│ later, as a message)
issued {{order}}
│ phase: executing
├── HAVE builder DO execute ──────────────► executes
│◄───────────────────────────── status, reply ──┘
├── HAVE planner DO review ────────► reviews
│◄─────────────────── status, reply ──┘
│ phase: closed
◄── "closed" ──────┘
# sprint-orders
An activity: it walks one work order through our sprint process — drafted
by the planner, issued by the director, executed by the builder, reviewed
by the planner — and keeps its own phase in `state.md`. `config.md` casts
`planner`, `builder`, `director`, and `me`.
# To open {{order}}
Record that the order is in play, then have the planner draft it.
```python
effects.write("state.md", '```json\n{"phase": "drafting", "order": "{{order}}"}\n```\n')
effects.append("narrative.md", "opened {{order}}\n")
```
Have "{{planner}}" do draft with order = "{{order}}"
The planner has returned: `{{status}}` is its exit status, `{{reply}}` the
path of its reply. Issuing is a human decision, so we ask the director and
stop — the answer arrives later as a message, not as a return.
```python
effects.write("state.md", '```json\n{"phase": "issuing", "order": "{{order}}"}\n```\n')
effects.append("narrative.md", "planner drafted {{order}} (status {{status}})\n")
```
Have "{{director}}" do receive with channel = "{{me}}", text = "please issue {{order}}: garden chirp {{me}} 'do issued with order = \"{{order}}\"'"
# To issued {{order}}
The director said go. Have the builder execute, then have the planner
review the builder's report.
```python
effects.write("state.md", '```json\n{"phase": "executing", "order": "{{order}}"}\n```\n')
effects.append("narrative.md", "director issued {{order}}\n")
```
Have "{{builder}}" do execute with order = "{{order}}"
```python
effects.append("narrative.md", "builder delivered {{order}}: report {{reply}} (status {{status}})\n")
```
Have "{{planner}}" do review with order = "{{order}}", report = "{{reply}}"
The verdict is one word in the planner's reply. Close either way — a
returned order is reopened by the director, not by us.
Do close with order = "{{order}}", verdict-file = "{{reply}}"
# To close {{order}} {{verdict-file}}
```python
from pathlib import Path
verdict = Path("{{verdict-file}}").read_text().strip()
effects.write("state.md", '```json\n{"phase": "closed", "order": "{{order}}", "verdict": "' + verdict + '"}\n```\n')
effects.append("narrative.md", "closed {{order}}: " + verdict + "\n")
```
Have "{{director}}" do receive with channel = "{{me}}", text = "{{order}} closed, see {{verdict-file}}"