Warm Runtime (Daemon)
Keep provider clients and MCP connections warm across praisonai run calls
from praisonaiagents import Agent
agent = Agent(name="daemon-agent", instructions="Run as a background daemon process.")
agent.start("Start the agent daemon and listen for incoming tasks.")praisonai daemon keeps provider clients and MCP connections hot in memory so repeated praisonai run calls skip cold-start entirely.
The user runs repeated praisonai run commands; the warm daemon forwards work to hot provider and MCP connections.
Quick Start
- Start the daemon in the background
bash praisonai daemon start --background✓ Warm runtime started in background at http://127.0.0.1:54321 (pid 12345)The daemon writes a project-local lockfile and binds to a free loopback port. All subsequent
praisonai runcalls in the same project directory automatically detect and attach to it.Edited commands, agents, skills, tools, and rules files (including
AGENTS.md/CLAUDE.md) are picked up on the next prompt. The daemon drops its warm agents and rebuilds them, and session history is rehydrated from the project session store. See Live edits during interactive sessions. - Run prompts — no extra flags needed
bash praisonai run "Write a haiku about clouds" praisonai run "Now make it rhyme" praisonai run "Translate to Spanish"Each call transparently attaches to the warm runtime. Provider and MCP clients are already initialised — only the prompt is forwarded.
- Check status and stop
bash praisonai daemon status✓ Warm runtime running at http://127.0.0.1:54321 (pid 12345).bash praisonai daemon stop✓ Stopped warm runtime (pid 12345).
How It Works
| Component | Role |
|---|---|
Lockfile (runtime.json) | Stores {host, port, token, pid} at <project_data_dir>/runtime/runtime.json. Mode 0600 — token is never world-readable. |
| WarmRuntime | Holds two agent caches: (1) one stateless warm Agent per model for anonymous (no-session) calls — history cleared after each call; (2) one stateful warm Agent per session id for --continue/--session runs — history rehydrated once and retained across turns, persisted per-turn through the project session store. Both caches evict on turn failure to prevent state bleed. |
| RuntimeClient | Thin stdlib (urllib) HTTP client. Raises RuntimeUnavailable on any error — run then falls back in-process. |
| Idle watcher | Background thread shuts down the server after --idle-timeout seconds of inactivity (default 30 min). |
Configuration Options
praisonai daemon start
| Flag | Type | Default | Description |
|---|---|---|---|
--host, -h | str | 127.0.0.1 | Loopback host to bind. Non-loopback addresses are rejected. |
--port, -p | int | 0 | Port to bind. 0 = auto-select a free port. |
--model, -m | str | None | Default model for the warm agent. |
--idle-timeout | float | 1800.0 | Seconds idle before auto-shutdown. 0 disables auto-shutdown. |
--background, -b | bool | False | Detach and run in the background. |
praisonai daemon status
| Flag | Type | Default | Description |
|---|---|---|---|
--json | bool | False | Output JSON for scripting. Returns {running, host, port, pid, base_url}. |
praisonai daemon status --json{
"running": true,
"host": "127.0.0.1",
"port": 54321,
"pid": 12345,
"base_url": "http://127.0.0.1:54321"
}praisonai daemon stop
No flags. Sends SIGTERM after a health-check ping to guard against PID reuse. Cleans up the lockfile.
When to Use Foreground vs Background
When --continue / --session Attach Warm
When run Stays In-Process
praisonai run skips the daemon and runs locally whenever you pass any of these flags:
| Flag(s) | Why it stays in-process |
|---|---|
--mcp, --tools, --toolset | Per-invocation tool overrides need in-process state. |
--approval, --approve-all-tools | Approval flow requires interactive in-process handling. |
--memory | Memory store is managed in-process. |
--permissions overrides | Security policy must be enforced locally. |
--fork | The forked session id is minted in-process; subsequent turns against the forked id attach warm. |
--thinking, --worktree | Reasoning-effort and isolated git-worktree runs need in-process state. |
--output actions, json, stream, stream-json | Structured output modes need richer in-process event bridging. |
In all these cases, praisonai run behaves exactly as it did before the daemon feature. No flags are needed to opt out — it happens automatically.
Common Patterns
Iterating on prompts in a shell loop
praisonai daemon start --background
for topic in clouds mountains rivers; do
praisonai run "Write a haiku about $topic"
done
praisonai daemon stopOnly the first call pays setup cost. The loop body is fast — just HTTP over loopback.
Auto-shutdown at night with –idle-timeout
# Shut down after 1 hour of inactivity (3600 seconds)
praisonai daemon start --background --idle-timeout 3600
# Or disable auto-shutdown entirely (not recommended for long sessions)
praisonai daemon start --background --idle-timeout 0The default is 1800 seconds (30 minutes). The daemon shuts itself down silently when the idle timer expires.
Scripting status checks
STATUS=$(praisonai daemon status --json)
RUNNING=$(echo "$STATUS" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['running'])")
if [ "$RUNNING" = "True" ]; then
echo "Daemon is up"
else
praisonai daemon start --background
fiThe --json flag returns {running, host, port, pid, base_url} — safe for jq or any JSON parser.
Using a specific model
praisonai daemon start --background --model gpt-4o
# All runs that don't specify --model will use gpt-4o from the warm agent
praisonai run "summarize this document"Security
Best Practices
Use –background for everyday workflows
Foreground mode is useful for debugging (you can see log output). For all other use cases, --background is simpler: it returns immediately and the daemon persists across terminal sessions.
Tune –idle-timeout carefully
The default 30-minute timeout is a good balance between warmth and resource usage. Setting --idle-timeout 0 means the daemon never shuts down automatically — only use this if you understand it will consume memory indefinitely.
One daemon per project
The lockfile is stored under the project data directory, scoped to the current project. Running two daemons in the same project will print a warning and exit. Each project directory gets its own independent daemon.
Check status before starting
praisonai daemon status
# → No warm runtime is running.
praisonai daemon start --backgroundStarting a daemon when one is already running prints a warning and exits cleanly — there is no risk of running two daemons accidentally.