OpenProgram: Self-Programming AI Agent Framework
Agents create and refine their own workflows · Any LLM · Any platform
Getting Started · Docs · API Reference · Philosophy · 中文
--- > *"The more constraints one imposes, the more one frees oneself."* > — **Igor Stravinsky**, *Poetics of Music* **We propose _Agentic Programming_.** An LLM is flexible; code is deterministic. Let the model run everything and you get chaos — unpredictable execution, context explosion, no output guarantees; hard-code everything and you lose the intelligence. A **harness** balances the two, interleaved moment to moment — **Python for the flow you want fixed, the LLM for the judgement you can't script.** ([the full rationale →](docs/capabilities/agentic-programming/philosophy.md)) > 🎉 **Paper:** [_LLM-as-Code: Agentic Programming for Agent Harness_](https://arxiv.org/abs/2606.15874) — accepted at the **KDD 2026 Workshop on Agentic Software Engineering (AgenticSE)**. ## News - **2026-07-21** — **v0.6.0** — multi-agent collaboration: `spawn` N sub-agents, message them across sessions, run file-touching branches in isolated git worktrees. - **2026-06-22** — **Paper accepted** at the KDD 2026 Workshop on Agentic Software Engineering ([arXiv:2606.15874](https://arxiv.org/abs/2606.15874)). - **2026-06-07** — **v0.5.0** — installable harnesses (`openprogram programs install
| Typical harness | OpenProgram |
|---|---|
| ```python TRIAGE_PROMPT = """You are a triage agent. Classify the ticket as bug, feature, or question. Reply as JSON.""" TOOLS = [{"type": "function", "function": { "name": "triage", "parameters": {"type": "object", "properties": {"ticket": {"type": "string"}}, "required": ["ticket"]}}}] resp = client.chat(TRIAGE_PROMPT, tools=TOOLS) kind = json.loads(resp)["kind"] # hope it parses if kind not in ("bug", "feature"): ... # and re-prompt by hand ``` | ```python @agentic_function def triage(ticket: str, runtime=None) -> str: """Classify the ticket as bug / feature / question, then draft a reply.""" kind = runtime.exec( # 🤖 LLM decides ticket, choices=["bug", "feature", "question"]) if kind == "bug": # 🐍 you decide logs = search_logs(ticket) # 🐍 plain Python return runtime.exec( # 🤖 LLM writes f"Reply using:\n{logs}") return runtime.exec("Draft a short reply.") ``` 🤖 `runtime.exec()` = **the LLM call** — one retryable DAG node 🐍 everything else = **plain Python**, runs every time |