> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Interactive Runtime Module

> Unified core runtime for all interactive modes with session management and approval flows

## Overview

The Interactive Runtime provides a **unified core runtime** that powers all interactive modes in PraisonAI:

* `praisonai chat` - Interactive chat mode
* `praisonai chat` - Interactive terminal chat mode
* `praisonai tui launch` - Full-screen TUI mode

All modes share the same:

* Session storage and continuation
* Tool dispatch and loading
* Permission/approval semantics
* Event-based architecture

## Installation

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
pip install praisonai
```

## Quick Start

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import asyncio
from praisonai.cli.features import InteractiveRuntime, RuntimeConfig

async def main():
    # Configure runtime
    config = RuntimeConfig(
        workspace="./my_project",
        lsp_enabled=True,
        acp_enabled=True,
        approval_mode="auto",
        trace_enabled=True
    )
    
    # Create and start runtime
    runtime = InteractiveRuntime(config)
    status = await runtime.start()
    
    print(f"LSP ready: {runtime.lsp_ready}")
    print(f"ACP ready: {runtime.acp_ready}")
    print(f"Read-only: {runtime.read_only}")
    
    # Use runtime for operations...
    
    await runtime.stop()

asyncio.run(main())
```

When the runtime is consumed via the PraisonAI YAML adapter (rather than constructed directly as above), startup failures now degrade gracefully — agents run without the runtime-backed centric tools instead of crashing the run.

## Configuration

### RuntimeConfig

| Parameter       | Type  | Default  | Description                         |
| --------------- | ----- | -------- | ----------------------------------- |
| `workspace`     | str   | "."      | Workspace root directory            |
| `lsp_enabled`   | bool  | True     | Enable LSP code intelligence        |
| `acp_enabled`   | bool  | True     | Enable ACP action orchestration     |
| `approval_mode` | str   | "manual" | Approval mode: manual, auto, scoped |
| `trace_enabled` | bool  | False    | Enable trace logging                |
| `trace_file`    | str   | None     | Path to save trace file             |
| `json_output`   | bool  | False    | Output JSON format                  |
| `timeout`       | float | 60.0     | Operation timeout in seconds        |
| `model`         | str   | None     | LLM model to use                    |
| `verbose`       | bool  | False    | Verbose output                      |

## Runtime Status

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
status = runtime.get_status()
```

Returns:

```json theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
{
  "started": true,
  "workspace": "/path/to/project",
  "lsp": {
    "enabled": true,
    "status": "ready",
    "ready": true,
    "error": null
  },
  "acp": {
    "enabled": true,
    "status": "ready",
    "ready": true,
    "error": null
  },
  "read_only": false,
  "approval_mode": "auto"
}
```

## Subsystem States

| Status        | Description                |
| ------------- | -------------------------- |
| `not_started` | Subsystem not initialized  |
| `starting`    | Subsystem is starting      |
| `ready`       | Subsystem is ready for use |
| `failed`      | Subsystem failed to start  |
| `stopped`     | Subsystem has been stopped |

## LSP Operations

When LSP is ready, you can use code intelligence:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Get symbols in a file
symbols = await runtime.lsp_get_symbols("main.py")

# Get definition location
definitions = await runtime.lsp_get_definition("main.py", line=10, col=5)

# Get references
references = await runtime.lsp_get_references("main.py", line=10, col=5)

# Get diagnostics
diagnostics = await runtime.lsp_get_diagnostics("main.py")
```

## ACP Operations

When ACP is ready, you can create and apply action plans:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Create a plan
plan = await runtime.acp_create_plan("Create a new file")

# Apply a plan
result = await runtime.acp_apply_plan(plan, auto_approve=True)
```

## Tracing

Enable tracing to capture all operations:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
config = RuntimeConfig(
    workspace="./project",
    trace_enabled=True,
    trace_file="trace.json"
)
runtime = InteractiveRuntime(config)
await runtime.start()

# ... perform operations ...

# Save trace
runtime.save_trace("my_trace.json")

# Get trace object
trace = runtime.get_trace()
print(trace.to_dict())
```

## Graceful Degradation

The runtime handles subsystem failures gracefully:

* **LSP fails**: Code intelligence falls back to regex-based extraction
* **ACP fails**: Runtime enters read-only mode (no file modifications)

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
if runtime.read_only:
    print("Warning: ACP unavailable, read-only mode")
```

## CLI Integration

The runtime integrates with CLI flags:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Enable LSP
praisonai chat --lsp

# Enable ACP with auto-approval
praisonai chat --acp --approval auto

# Enable tracing
praisonai chat --trace --trace-file session.json
```

## Lifecycle in YAML runs (`framework: praisonai`)

Setting `config.acp: true` or `config.lsp: true` in YAML triggers the same `InteractiveRuntime` lifecycle as the Python API:

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
framework: praisonai
topic: Refactor the auth module

config:
  acp: true
  lsp: true

roles:
  refactorer:
    role: Code Refactorer
    goal: Tighten auth.py for readability and safety
    backstory: Staff engineer, security-minded.
    tasks:
      refactor:
        description: Refactor the auth module in {topic}
        expected_output: Diff applied via the agent-centric tools.
```

### YAML Runtime Lifecycle

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant YAML as YAML Parser
    participant Bridge as _async_bridge (shared loop)
    participant Runtime as InteractiveRuntime
    participant Tools as Agent Tools
    participant Team as AgentTeam

    YAML->>Bridge: run_sync(runtime.start())
    Bridge->>Runtime: start() on persistent bg loop
    Runtime->>Tools: create_agent_centric_tools(runtime)
    Tools->>YAML: Merge into tools_dict
    YAML->>Team: team.start() with merged tools
    Team->>Tools: tool_call → run_sync(_coro())
    Tools->>Bridge: re-enters SAME loop
    Bridge-->>Tools: result
    Team-->>YAML: Agent execution result
    YAML->>Bridge: run_sync(runtime.stop()) (finally block)
```

### YAML Configuration Details

The YAML route uses default `RuntimeConfig` values with these settings:

* **Workspace**: `os.getcwd()` (current working directory)
* **Approval Mode**: `PRAISONAI_APPROVAL_MODE` environment variable (default: `"prompt"`)
* **Trace Enabled**: Not explicitly set (uses RuntimeConfig default)

The runtime boots on the **shared `_async_bridge` background loop** (the same loop already used by \~77 wrapper-side `run_sync` callers), not on a per-run scoped loop. This is what makes ACP/LSP agent-centric tools safe — every async primitive owned by the runtime stays bound to a loop that is **still running** when tools re-enter.

`run_sync()` now cancels the runtime startup/shutdown coroutine on timeout (PR #1692), so a hung LSP server or ACP backend no longer leaks.

### Full RuntimeConfig Control

For full `RuntimeConfig` control, use the Python API directly:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import asyncio
from praisonai.cli.features import InteractiveRuntime, RuntimeConfig
from praisonaiagents import Agent, AgentTeam

async def advanced_workflow():
    config = RuntimeConfig(
        workspace="/custom/path",
        approval_mode="auto",
        trace_enabled=True,
        lsp_enabled=True,
        acp_enabled=True
    )
    
    runtime = InteractiveRuntime(config)
    await runtime.start()
    
    # Create agents with runtime tools
    from praisonai.cli.features.agent_tools import create_agent_centric_tools
    tools = create_agent_centric_tools(runtime)
    
    agent = Agent(name="Dev", tools=list(tools.values()))
    team = AgentTeam(agents=[agent])
    
    result = team.start()
    await runtime.stop()
    
    return result

# Run the workflow
result = asyncio.run(advanced_workflow())
```

<Info>
  For more details on agent-centric tools and InteractiveRuntime integration, see [PraisonAI Agents Framework](/docs/framework/praisonaiagents).

  **As of PR #1658 (May 2026), ACP/LSP agent-centric tools work end-to-end in YAML runs. Earlier versions had a premature-teardown bug — upgrade to praisonai ≥ 0.0.58.**

  **PR #1692 (May 2026)** — `run_sync()` now cancels timed-out tasks on the background loop, and YAML `tool_timeout` is enforced at the wrapper boundary as well as inside the SDK. Upgrade to praisonai ≥ the release containing this PR for both behaviours.
</Info>

## Operational Notes

### Performance

* Subsystems start in parallel for faster initialization
* LSP client is lazy-loaded only when enabled
* ACP session is lightweight (in-process)

### Dependencies

* `pylsp` (optional) - For Python LSP support
* `pyright` (optional) - Alternative Python LSP

### Production Caveats

* LSP startup may take a few seconds for large workspaces
* Trace files can grow large for long sessions
* ACP session is in-memory; external storage needed for persistence

### Concurrency safety

`InteractiveRuntime.start()` and `.stop()` are coroutines. The CLI boots them through the persistent background loop via the [Async Bridge](/docs/features/async-bridge), so they are safe to call from sync code (e.g. inside `PraisonAI._run_praisonai`). Calling `PraisonAI.run()` from **inside** a running event loop raises `RuntimeError` instead of deadlocking — wrap your async caller around the runtime directly instead.

**Session-store concurrency.** The CLI session store (`praisonai.cli.session.UnifiedSessionStore`) used by TUI, `--interactive`, and `InteractiveCore` is safe across processes and threads as of [PR #1854](https://github.com/MervinPraison/PraisonAI/pull/1854). `save()` reloads the on-disk JSON under an exclusive lock and merges concurrent message appends rather than overwriting them; `load()` invalidates the in-memory cache when the on-disk file's mtime has advanced. See [CLI Sessions → Concurrent Sessions](/docs/cli/session#concurrent-sessions) for the user-facing description.

<Card icon="arrows-left-right" href="/docs/features/async-bridge">
  How sync/async crossings work in the wrapper layer
</Card>

## InteractiveCore (Unified Runtime)

The new `InteractiveCore` provides a unified runtime for all interactive modes:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.cli.interactive import InteractiveCore, InteractiveConfig

# Create config
config = InteractiveConfig(
    model="gpt-4o-mini",
    continue_session=True,  # Resume last session
    files=["README.md"],    # Attach files
    
)

# Create core
core = InteractiveCore(config=config)

# Create or continue session
if config.continue_session:
    session_id = core.continue_session()
else:
    session_id = core.create_session(title="My Session")

# Execute prompt
import asyncio
response = asyncio.run(core.prompt("Hello!"))
print(response)
```

### CLI Flags

| Flag          | Short | Description              |
| ------------- | ----- | ------------------------ |
| `--model`     | `-m`  | LLM model to use         |
| `--session`   | `-s`  | Session ID to resume     |
| `--continue`  | `-c`  | Continue last session    |
| `--file`      | `-f`  | Attach file(s) to prompt |
| `--workspace` | `-w`  | Workspace directory      |
| `--verbose`   | `-v`  | Verbose output           |
| `--memory`    |       | Enable memory            |

### Session Management

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# List sessions
praisonai session list

# Export session
praisonai session export <session_id> --output session.json

# Import session
praisonai session import session.json

# Continue last session
praisonai chat --continue "What was my last question?"
```

### Approval Modes

The runtime supports three approval modes:

| Mode     | Description                           |
| -------- | ------------------------------------- |
| `prompt` | Ask user for each action (default)    |
| `auto`   | Auto-approve all actions              |
| `reject` | Reject all actions requiring approval |

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
config = InteractiveConfig(approval_mode="auto")
```

## Related

* [Agent-Centric Tools](/cli/agent-tools) - Tools powered by this runtime
* [Debug CLI](/cli/debug-cli) - Debug commands
* [ACP](/cli/acp) - Agent Communication Protocol
