Software as Content — Conversations that produce evolving software. An open-source Python SDK that gives any agent the ability to generate and evolve interactive apps through conversation.
Project description
SaC (Software as Content) is an interaction layer that gives your AI agent the ability to generate and evolve interactive apps as part of the conversation. Instead of replying with text or markdown, your agent builds a live React app — a dashboard, a planner, a comparison tool — and the user clicks, types, and explores. The agent then evolves the same app in response, preserving all context across turns.
This isn't one-shot UI generation. SaC apps are stateful, conversational, and evolving — the agent understands what the user is looking at, what they clicked, and grows the app from there. No existing agent can do this natively.
function calling → agent does things · MCP → agent talks to systems · SaC → agent shows, interacts, and evolves
Quickstart
1. Install
pip install sac-sdk
2. Configure your LLM
cp .env.example .env
Edit .env and add your API key. SaC uses an LLM to generate the apps — any OpenAI-compatible provider works:
# OpenRouter (default), Anthropic, OpenAI, Ollama, etc.
SAC_API_KEY=sk-or-v1-your-key-here
# Optional: custom endpoint for OpenAI direct, Ollama, vLLM, etc.
# SAC_API_BASE=https://api.openai.com/v1/chat/completions
3. Run
sac serve
Open http://localhost:18420, type "3-day Tokyo trip planner with budget", and watch a live React app stream in. Click buttons. Ask it to evolve. This is SaC running a built-in agent loop — no external agent needed.
Connect to your agent
SaC plugs into the agent you already use — through MCP, Skill, or code.
Claude Code (MCP)
pip install sac-sdk
sac setup claude-code # registers SaC as an MCP server
Restart Claude Code. Then try:
"Create an interactive release-readiness dashboard for this repo using SaC."
Claude Code will generate the app, show you the URL, and enter the interaction loop automatically.
Codex (Skill)
pip install sac-sdk
sac setup codex # installs the SaC skill
sac serve # keep running in a terminal
OpenClaw (Skill)
pip install sac-sdk
sac setup openclaw # installs the SaC skill
sac serve # keep running in a terminal
Python (build your own agent)
from sac import SaC
sac = SaC()
conv = sac.conversation()
app = await conv.generate("3-day Tokyo itinerary")
print(app.url) # user opens this
# app.code contains the generated TSX
How it works
Your agent ──▶ SaC ──▶ User sees a live app at a URL
◀── User clicks a button / types a message
Your agent ──▶ SaC ──▶ Same URL, app evolves in place
◀── ...
One URL, one conversation. The agent doesn't generate a new page every turn — it evolves the existing app. Users keep their context; the agent keeps its state.
Two channels, one loop: every response is either a UI update (the app evolves) or a chat reply (a text bubble). Users can click buttons in the app OR type in the chat — both go back to the agent through the same callback.
When to use SaC
SaC is for tasks where exploration and interaction matter more than a final answer.
Good fit: trip planning, data analysis dashboards, comparison shopping, project planning, research, financial reviews, decision aids, internal tools
Not the right tool for: simple Q&A, one-shot automations ("set an alarm"), conversations that are purely text
Customize
Every layer is pluggable:
from sac import SaC, FileStore
sac = SaC(
llm=YourLLMProvider(...), # any class implementing LLMProvider
search=YourSearchProvider(...), # any class implementing SearchProvider
store=FileStore(".sac"),
)
Prompts live in src/sac/runtime/prompts/ and
the default design system is in src/sac/renderer/design-systems/default/.
Architecture
src/sac/
├── sac.py / conversation.py Entry + Conversation primitive
├── runtime/ Generate + Evolve pipeline, prompts, providers
├── server/
│ ├── http/ FastAPI + SSE streaming + viewer
│ └── mcp/ MCP stdio server (Claude Code integration)
└── renderer/ iframe sandbox + design system
Project status
Alpha. The core protocol (generate → evolve → callback loop) is stable and runs in production at sac.dynsoft.ai. The SDK surface is being polished toward v1.0.
Contributing
Issues and PRs welcome. Highest-leverage contributions right now:
- Prompt improvements in
src/sac/runtime/prompts/ - Design system contributions in
src/sac/renderer/design-systems/
For local dev: pip install -e .
Citation
@article{xie2026sac,
title = {Software as Content: Dynamic Applications as the Human-Agent Interaction Layer},
author = {Xie, Mulong},
year = {2026},
url = {https://arxiv.org/abs/2603.21334}
}
License
Apache-2.0 · © 2026 Mulong Xie / Dynsoft Lab
Built by Dynsoft Lab. Questions: mulong@mulongxie.me
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sac_sdk-0.1.0.tar.gz.
File metadata
- Download URL: sac_sdk-0.1.0.tar.gz
- Upload date:
- Size: 239.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34c9d572c859ce95c138ed3391d8ef8e1beba33e037a866ba878d780f0e1e93d
|
|
| MD5 |
94748a073603d90c24a2e91b6c76cb98
|
|
| BLAKE2b-256 |
c64ef9630f6c589da1ef0cb96d2119f535ff3ed2193db4705105383df1e99345
|
File details
Details for the file sac_sdk-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sac_sdk-0.1.0-py3-none-any.whl
- Upload date:
- Size: 253.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6ce89566782a0d088c1e8ccf1edd5eb361e25f86a471b2638754b37d9e70e88
|
|
| MD5 |
908dffd1bf7f40fcf5f090cd64c53055
|
|
| BLAKE2b-256 |
4dd25d381173456aeaf7aae2e32580879b08347f0cd8cf76a106bc37ec26abb6
|