RDPGE: Runtime Dynamic & Probabilistic Graph Execution — A novel paradigm for agentic AI
Project description
RDPGE
Runtime Dynamic & Probabilistic Graph Execution
A novel agentic AI framework that treats LLM outputs as probabilistic events, not deterministic programs.
RDPGE replaces the flat ReAct loop with a dynamic execution graph — giving agents structured memory, selective context, and real-time situational awareness.
Why RDPGE?
Standard agentic frameworks (ReAct, function-calling loops) suffer from three core problems:
| Problem | What Happens | RDPGE's Solution |
|---|---|---|
| Myopia | The agent only sees recent context. Work done 15 steps ago fades from attention. | Graph Manifest — a live dashboard showing all tasks, distances, references, and step budget. Updated every turn. |
| Greedy execution | The agent does the first thing that seems useful without considering the bigger picture. | Task-based organization — work is structured into named tasks. The agent sees the full map before acting. |
| Context waste | All tool outputs stay in context forever, consuming tokens even when irrelevant. | Context blurring — inactive tasks' tool outputs are replaced with [BLURRED]. Restored on demand via edges. |
Key Ideas
- Code-as-interface — The LLM outputs Python code, not JSON tool calls. Comments serve as chain-of-thought. An
actiondictionary is the structured interface. - Probabilistic graph — Execution is tracked as a dynamic graph of nodes organized by tasks. The LLM creates tasks and nodes as needed.
- Context blurring — Only the active task's tool outputs are visible. Everything else is
[BLURRED]. The LLM can restore any task's context by creating an edge. - Graph manifest — Every turn, the LLM sees a live dashboard: active node, current task, step budget, task distances, and inter-task references.
- Signal tools — Built-in tools (
complete,ask_user,surrender) that control execution flow explicitly.
Install
pip install rdpge
Quick Start
import asyncio
from rdpge import Agent, tool
from rdpge.llm import OpenAIAdapter, LLMConfig
# 1. Define tools
@tool()
def read_file(path: str) -> str:
"""Read file contents from disk."""
with open(path) as f:
return f.read()
@tool()
def write_file(path: str, content: str) -> str:
"""Write content to a file on disk."""
with open(path, "w") as f:
f.write(content)
return f"Written {len(content)} bytes to {path}"
# 2. Create agent
agent = Agent(
llm=OpenAIAdapter(LLMConfig(
model="gpt-4o",
api_key="sk-...",
)),
tools=[read_file, write_file],
instructions="You are a code assistant.",
max_steps=25,
)
# 3. Run
async def main():
result = await agent.run("Read auth.py and fix the login bug")
print(f"Status: {result.status}")
print(f"Steps used: {result.steps}")
print(f"Reason: {result.reason}")
asyncio.run(main())
Using with Together AI
from rdpge.llm import OpenAIAdapter, LLMConfig
llm = OpenAIAdapter(LLMConfig(
model="Qwen/Qwen3-Coder-480B-A35B-Instruct",
api_key="your-together-key",
base_url="https://api.together.xyz/v1",
))
agent = Agent(llm=llm, tools=[...])
Using with Anthropic
from rdpge.llm import AnthropicAdapter, LLMConfig
llm = AnthropicAdapter(LLMConfig(
model="claude-sonnet-4-20250514",
api_key="sk-ant-...",
))
agent = Agent(llm=llm, tools=[...])
How It Works
User Request
│
▼
┌─────────────────────────────────────────────┐
│ EXECUTION LOOP │
│ │
│ 1. Build Context │
│ ├── System Prompt │
│ ├── Graph Manifest (live dashboard) │
│ └── Node History (with blurring) │
│ │
│ 2. LLM Generates Python Code │
│ └── action = {node, reason, tool_call} │
│ │
│ 3. Execute Code in Sandbox │
│ └── Extract action dict │
│ │
│ 4. Route Tool Call │
│ ├── Signal tool? → Handle internally │
│ └── Regular tool? → Execute via registry│
│ │
│ 5. Update Graph │
│ ├── Record node in task │
│ ├── Apply blurring to inactive tasks │
│ └── Save state (multi-turn) │
│ │
│ 6. Loop until: complete / surrender / │
│ ask_user / max_steps │
└─────────────────────────────────────────────┘
│
▼
AgentResult(status, reason, steps, trace, graph)
The Graph Manifest
Every turn, the LLM sees this dashboard in its context:
{
"tasks": {
"a": {
"status": "inactive",
"steps": 3,
"distance": 2,
"references": 0
},
"b": {
"status": "active",
"steps": 2
"distance": 0,
"references": 0
}
},
"edges": [],
"runtime": {
"step": 6,
"active_node": "node-b2",
"current_task": "b",
"restored_context": null
}
}
- Distance tells the LLM how far back a task is (recency).
- References show inter-task dependencies (importance).
- Step counter shows remaining budget (the hard execution limit).
Context Blurring
When the LLM switches from Task A to Task B:
# Task A's tool outputs become:
Tool: [BLURRED]
# Task B's tool outputs remain fully visible:
Tool: def login(user, pwd): ...
The LLM can restore Task A's context by calling restore_context(task="a").
Signal Tools
Built-in tools that control execution flow:
| Signal | Args | Effect |
|---|---|---|
complete |
{} |
Task is done. Loop ends. |
ask_user |
{"question": str} |
Pauses execution. Returns the question to the caller. |
surrender |
{"reason": str} |
Cannot accomplish the task. Loop ends. |
Developer-side abort:
# From a UI button or hook callback:
agent.abort("User pressed cancel")
Multi-Turn Sessions
RDPGE preserves full graph state between conversations:
# Turn 1
result = await agent.run("Read the codebase and find bugs")
# result.status == "awaiting_input" (agent used ask_user)
# Turn 2 — agent remembers everything from Turn 1
result = await agent.run("Focus on auth.py")
Persistence
from rdpge import Agent, InMemoryStore
# In-memory (default)
agent = Agent(llm=llm, tools=[...], store=InMemoryStore())
# Custom store (Redis, database, etc.)
# Implement the SessionStore protocol:
class RedisStore:
async def save(self, session_id: str, data: dict) -> None: ...
async def load(self, session_id: str) -> dict | None: ...
async def delete(self, session_id: str) -> None: ...
async def list_sessions(self) -> list[str]: ...
Event Hooks
Monitor and react to agent behavior:
@agent.on("step_end")
async def log_step(data):
print(f"Step {data['step']}: {data['node_id']} → {data['tool']}")
@agent.on("complete")
async def on_done(data):
print(f"Finished in {data['steps']} steps")
@agent.on("surrender")
async def on_surrender(data):
print(f"Gave up: {data['reason']}")
Available events: step_start, step_end, tool_called, complete, ask_user, surrender, abort, error
Execution Traces
Every run produces a detailed trace:
result = await agent.run("Fix the bug")
summary = result.trace.summary()
print(summary)
# {
# "session_id": "a1b2c3d4",
# "total_steps": 5,
# "total_duration_ms": 12340,
# "tools_used": {"read_file": 2, "write_file": 1, "complete": 1, ...},
# "nodes": ["node-a1", "node-a2", "node-a3", "node-b1", "node-b2"],
# }
API Reference
Agent
Agent(
llm, # LLMProvider instance
tools: list = None, # List of @tool() or BaseTool instances
instructions: str = "", # Domain-specific instructions for the LLM
instructions_file: str = None,# Or load instructions from a file
max_steps: int = 25, # Hard execution limit
store = None, # SessionStore for persistence
signal_handlers: dict = None, # Override signal tool behavior
)
Methods:
await agent.run(request)→AgentResultagent.abort(reason)— stop execution from outsideagent.new_session()— start freshawait agent.load_session(session_id)→boolagent.on(event)— decorator for event hooks
AgentResult
@dataclass
class AgentResult:
success: bool # True if task completed successfully
status: str # "completed" | "awaiting_input" | "surrendered" | "aborted" | "max_steps" | "error"
reason: str # Human-readable summary
steps: int # Number of steps executed
session_id: str # Session identifier
trace: SessionTrace # Execution trace
graph: GraphState # Final graph state
error: str = "" # Error details (if status == "error")
@tool()
@tool()
def my_tool(param: str) -> str:
"""Tool description (used in the LLM prompt)."""
return result
# Or with explicit description:
@tool("Override the docstring description")
def my_tool(param: str) -> str:
...
Architecture
RDPGE is built on four principles:
-
Respect probabilistic nature — LLM outputs are unpredictable. The framework handles malformed outputs, retries, and edge cases structurally.
-
Overcome myopia — The graph manifest gives the LLM a bird's-eye view of its entire session, preventing short-sighted decisions.
-
Ensure task accuracy — Signal tools (
surrender,ask_user) let the agent be honest about its limitations instead of producing garbage output. -
Complete observability — Traces, hooks, and graph export provide full transparency into agent behavior at every level.
License
MIT
Author
Jahanzeb Ahmed — GitHub
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 rdpge-0.2.0.tar.gz.
File metadata
- Download URL: rdpge-0.2.0.tar.gz
- Upload date:
- Size: 34.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1659f5d8cb61b898470daa3803b3aa5e8642896569bd95aa6ff373a957502d5e
|
|
| MD5 |
2e6c6875aa50b6a7172cdff80e3d68ef
|
|
| BLAKE2b-256 |
c97327cae6818253d59148fd99696c83c04f7bcd3622c95a6d6e2211725eb5c6
|
Provenance
The following attestation bundles were made for rdpge-0.2.0.tar.gz:
Publisher:
publish.yml on Jahanzeb-git/rdpge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rdpge-0.2.0.tar.gz -
Subject digest:
1659f5d8cb61b898470daa3803b3aa5e8642896569bd95aa6ff373a957502d5e - Sigstore transparency entry: 955144892
- Sigstore integration time:
-
Permalink:
Jahanzeb-git/rdpge@0ff4b9a76e51daaa4de98ac36d84f7e9c8005632 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Jahanzeb-git
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0ff4b9a76e51daaa4de98ac36d84f7e9c8005632 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rdpge-0.2.0-py3-none-any.whl.
File metadata
- Download URL: rdpge-0.2.0-py3-none-any.whl
- Upload date:
- Size: 34.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c338e226b7101a306a946035e32a65b9183fe4d110ef44af1dbd607dc9804a5
|
|
| MD5 |
6399400bfd4f975a215d66b66bb2bd7c
|
|
| BLAKE2b-256 |
44576676726b2572275536a255d9451f5b95aaf9f64c8f3fea5e0029d14e1ae4
|
Provenance
The following attestation bundles were made for rdpge-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on Jahanzeb-git/rdpge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rdpge-0.2.0-py3-none-any.whl -
Subject digest:
5c338e226b7101a306a946035e32a65b9183fe4d110ef44af1dbd607dc9804a5 - Sigstore transparency entry: 955144893
- Sigstore integration time:
-
Permalink:
Jahanzeb-git/rdpge@0ff4b9a76e51daaa4de98ac36d84f7e9c8005632 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Jahanzeb-git
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0ff4b9a76e51daaa4de98ac36d84f7e9c8005632 -
Trigger Event:
push
-
Statement type: