Skip to content

Commit 33cc2a9

Browse files
committed
Release v4.5.148
1 parent d4a8b47 commit 33cc2a9

22 files changed

Lines changed: 758 additions & 170 deletions

File tree

docker/Dockerfile.chat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
1616
# Install Python packages (using latest versions)
1717
RUN pip install --no-cache-dir \
1818
praisonai_tools \
19-
"praisonai>=4.5.147" \
19+
"praisonai>=4.5.148" \
2020
"praisonai[chat]" \
2121
"embedchain[github,youtube]"
2222

docker/Dockerfile.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ RUN mkdir -p /root/.praison
2020
# Install Python packages (using latest versions)
2121
RUN pip install --no-cache-dir \
2222
praisonai_tools \
23-
"praisonai>=4.5.147" \
23+
"praisonai>=4.5.148" \
2424
"praisonai[ui]" \
2525
"praisonai[chat]" \
2626
"praisonai[realtime]" \

docker/Dockerfile.ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ RUN mkdir -p /root/.praison
1616
# Install Python packages (using latest versions)
1717
RUN pip install --no-cache-dir \
1818
praisonai_tools \
19-
"praisonai>=4.5.147" \
19+
"praisonai>=4.5.148" \
2020
"praisonai[ui]" \
2121
"praisonai[crewai]"
2222

examples/python/managed_agent_example.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,10 @@ def example_1_standalone():
3535
print("Example 1: Standalone ManagedAgentIntegration")
3636
print("=" * 60)
3737

38-
from praisonai.integrations import ManagedAgentIntegration
39-
from praisonaiagents import ManagedBackendConfig
38+
from praisonai.integrations.managed_agents import ManagedAgent, ManagedConfig
4039

41-
managed = ManagedAgentIntegration(
42-
config=ManagedBackendConfig(
40+
managed = ManagedAgent(
41+
config=ManagedConfig(
4342
model="claude-sonnet-4-6",
4443
name="Standalone Test Agent",
4544
system="You are a concise assistant. Answer in one sentence.",
@@ -60,11 +59,11 @@ def example_2_with_agent():
6059
print("Example 2: PraisonAI Agent with managed backend")
6160
print("=" * 60)
6261

63-
from praisonaiagents import Agent, ManagedBackendConfig
64-
from praisonai.integrations import ManagedAgentIntegration
62+
from praisonaiagents import Agent
63+
from praisonai.integrations.managed_agents import ManagedAgent, ManagedConfig
6564

66-
managed = ManagedAgentIntegration(
67-
config=ManagedBackendConfig(
65+
managed = ManagedAgent(
66+
config=ManagedConfig(
6867
model="claude-sonnet-4-6",
6968
name="PraisonAI Backend Agent",
7069
system="You are a helpful coding assistant. Be concise.",
@@ -90,11 +89,11 @@ def example_3_with_tools():
9089
print("Example 3: Managed agent with built-in tools")
9190
print("=" * 60)
9291

93-
from praisonaiagents import Agent, ManagedBackendConfig
94-
from praisonai.integrations import ManagedAgentIntegration
92+
from praisonaiagents import Agent
93+
from praisonai.integrations.managed_agents import ManagedAgent, ManagedConfig
9594

96-
managed = ManagedAgentIntegration(
97-
config=ManagedBackendConfig(
95+
managed = ManagedAgent(
96+
config=ManagedConfig(
9897
model="claude-sonnet-4-6",
9998
name="Tool-Using Agent",
10099
system="You are a coding agent with access to bash and file tools.",
@@ -123,11 +122,11 @@ def example_4_with_packages():
123122
print("Example 4: Managed agent with pip packages")
124123
print("=" * 60)
125124

126-
from praisonaiagents import Agent, ManagedBackendConfig
127-
from praisonai.integrations import ManagedAgentIntegration
125+
from praisonaiagents import Agent
126+
from praisonai.integrations.managed_agents import ManagedAgent, ManagedConfig
128127

129-
managed = ManagedAgentIntegration(
130-
config=ManagedBackendConfig(
128+
managed = ManagedAgent(
129+
config=ManagedConfig(
131130
model="claude-sonnet-4-6",
132131
name="Data Agent",
133132
system="You are a data analysis agent. Use pandas when helpful.",

examples/terminal_bench/praisonai_external_agent.py

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -121,24 +121,22 @@ async def bash_tool(command: str) -> str:
121121
agent = Agent(
122122
name="terminal-agent",
123123
instructions=(
124-
"You are an expert terminal agent working on coding, security, and system administration tasks. "
125-
"Use the bash_tool to execute shell commands in the sandboxed environment. "
124+
"You are an expert terminal agent. You solve coding, debugging, data analysis, security, "
125+
"and system administration tasks using the bash_tool to run shell commands."
126126
"\n\nCRITICAL RULES:"
127-
"\n1. ALWAYS start by reading ALL relevant files: "
128-
" ls /app/ && ls /tests/ 2>/dev/null && cat /app/*.py 2>/dev/null && cat /tests/*.py 2>/dev/null || true"
129-
" Read EVERY source file including the test/verifier scripts to understand exactly what passes."
130-
"\n2. Run the test IMMEDIATELY after reading files to see the current failure message: "
131-
" cd /app && python3 -m pytest /app/test_outputs.py -v 2>&1 | tail -50 || true"
132-
" The error trace tells you EXACTLY what the test expects."
133-
"\n3. For writing files with special characters (quotes, backslashes, parentheses), "
134-
" ALWAYS use Python: python3 -c \"with open('/app/out.html','w') as f: f.write('...')\""
135-
"\n4. ITERATE: Try an approach, run the test, read the error, try again. Keep going until the test passes."
136-
" Never give up after one attempt — try multiple different approaches."
137-
"\n5. Read error messages carefully — they tell you exactly what to fix next."
138-
"\n6. If the task involves bypassing/exploiting/breaking something: "
139-
" experiment with many different payloads, test each one, and use the test output to guide you."
140-
"\n7. NEVER stop to describe or explain what you plan to do. ALWAYS immediately call "
141-
" bash_tool to execute commands. Keep using bash_tool until the test PASSES."
127+
"\n1. START by exploring: ls /app/ && cat /app/*.py /app/*.sh /app/*.txt 2>/dev/null | head -200"
128+
" Read ALL task files to understand what is needed before doing anything."
129+
"\n2. Find and run the test IMMEDIATELY to see what is expected:"
130+
" find /app -name 'test_*.py' | head -3 && cd /app && python3 -m pytest -v 2>&1 | tail -40 || true"
131+
" The test error trace tells you EXACTLY what output/behavior is required."
132+
"\n3. ITERATE: implement a solution, run the test, read the error, refine. Repeat until it passes."
133+
" Never give up after one attempt — try multiple approaches if needed."
134+
"\n4. For writing files with special characters use Python:"
135+
" python3 -c \"with open('/app/file','w') as f: f.write('content')\""
136+
" or heredoc: cat > /app/file << 'EOF'\\n...content...\\nEOF"
137+
"\n5. Read ALL error messages — they tell you exactly what to fix next."
138+
"\n6. NEVER just describe your plan. ALWAYS immediately run bash_tool commands."
139+
" Keep calling bash_tool until the test PASSES or you have exhausted all approaches."
142140
),
143141
tools=[bash_tool],
144142
llm=self.model_name or "openai/gpt-4o",
@@ -149,17 +147,17 @@ async def bash_tool(command: str) -> str:
149147
result = await agent.achat(instruction)
150148
for _iter in range(19):
151149
result_str = str(result)
152-
# Stop if test passed or we have clear completion
150+
# Stop if test passed
153151
if any(sig in result_str.lower() for sig in [
154-
"passed", "1 passed", "test passed", "all tests"
152+
" passed", "passed ", "test passed", "all tests pass", "1 passed"
155153
]):
156154
break
157155
result = await agent.achat(
158-
"The task is NOT complete yet. You must keep working. "
159-
"Run bash_tool commands now — do not explain, just act. "
160-
"If you have not yet created /app/out.html, create it now with a JS payload that bypasses the filter. "
161-
"Then run: python3 /app/test_outputs.py to check if it passes. "
162-
"Keep iterating until the test passes."
156+
"The task is NOT complete yetkeep working. Run bash_tool commands now. "
157+
"If you haven't already: (1) read all files in /app/, "
158+
"(2) run the test to see the exact failure, "
159+
"(3) implement a fix, (4) run the test again. "
160+
"Repeat until the test passes. What is your next bash_tool command?"
163161
)
164162
print(f"✅ PraisonAI Agent completed task")
165163

src/praisonai-agents/praisonaiagents/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,9 +456,8 @@ def _get_lazy_cache():
456456
'SandboxConfig': ('praisonaiagents.sandbox.config', 'SandboxConfig'),
457457
'SecurityPolicy': ('praisonaiagents.sandbox.config', 'SecurityPolicy'),
458458

459-
# Managed backend protocols (implementations in praisonai wrapper)
459+
# Managed backend protocol (implementation + config in praisonai wrapper)
460460
'ManagedBackendProtocol': ('praisonaiagents.agent.protocols', 'ManagedBackendProtocol'),
461-
'ManagedBackendConfig': ('praisonaiagents.agent.protocols', 'ManagedBackendConfig'),
462461

463462
# Model failover
464463
'AuthProfile': ('praisonaiagents.llm.failover', 'AuthProfile'),

src/praisonai-agents/praisonaiagents/agent/execution_mixin.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,12 @@ def run(self, prompt: str, **kwargs: Any) -> Optional[str]:
279279
return result
280280

281281
def _delegate_to_backend(self, prompt: str, **kwargs) -> Optional[str]:
282-
"""Delegate execution to external managed backend (e.g., ManagedAgentIntegration)."""
282+
"""Delegate execution to external managed backend (e.g., ManagedAgentIntegration).
283+
284+
Also records the prompt and response in the Agent's chat_history so that
285+
PraisonAI's session management (SessionStore, auto_save) stays consistent
286+
with managed-backend conversations.
287+
"""
283288
import asyncio
284289

285290
# Check if backend satisfies ManagedBackendProtocol
@@ -291,15 +296,31 @@ def _delegate_to_backend(self, prompt: str, **kwargs) -> Optional[str]:
291296
stream_requested = kwargs.get('stream', False)
292297

293298
if stream_requested:
294-
# For streaming, delegate to backend's stream method if available
295299
if hasattr(self.backend, 'stream'):
296-
return self._delegate_streaming_to_backend(prompt, **kwargs)
300+
result = self._delegate_streaming_to_backend(prompt, **kwargs)
297301
else:
298-
# Fallback: execute non-streaming even if stream was requested
299-
return self._execute_backend_sync(prompt, **kwargs)
302+
result = self._execute_backend_sync(prompt, **kwargs)
300303
else:
301-
# Non-streaming execution
302-
return self._execute_backend_sync(prompt, **kwargs)
304+
result = self._execute_backend_sync(prompt, **kwargs)
305+
306+
# ── Chat history & session linkage ──
307+
# Record prompt+response in chat_history so SessionStore/auto_save works
308+
if result is not None and not stream_requested:
309+
self.chat_history.append({"role": "user", "content": prompt})
310+
self.chat_history.append({"role": "assistant", "content": str(result)})
311+
# Link managed session ID into SessionStore gateway_session_id
312+
if hasattr(self.backend, 'managed_session_id'):
313+
msid = self.backend.managed_session_id
314+
if msid and self._session_store is not None:
315+
try:
316+
sid = getattr(self, 'auto_save', None) or getattr(self, '_session_id', None)
317+
if sid and hasattr(self._session_store, 'set_gateway_info'):
318+
self._session_store.set_gateway_info(sid, gateway_session_id=msid)
319+
except Exception:
320+
pass # Best-effort linkage
321+
self._auto_save_session()
322+
323+
return result
303324

304325
def _execute_backend_sync(self, prompt: str, **kwargs) -> Optional[str]:
305326
"""Execute backend in sync mode, handling async backends."""

src/praisonai-agents/praisonaiagents/agent/protocols.py

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
These protocols are lightweight and have zero performance impact.
1111
"""
1212
from typing import Protocol, runtime_checkable, Optional, Any, AsyncIterator, Dict, List
13-
from dataclasses import dataclass, field
1413

1514

1615
@runtime_checkable
@@ -303,44 +302,6 @@ def launch(
303302
...
304303

305304

306-
@dataclass
307-
class ManagedBackendConfig:
308-
"""Configuration for managed agent backends.
309-
310-
Portable dataclass that describes *what* to create on the managed
311-
infrastructure without tying to any provider SDK.
312-
313-
Example::
314-
315-
cfg = ManagedBackendConfig(
316-
model="claude-sonnet-4-6",
317-
system="You are a coding assistant.",
318-
tools=[{"type": "agent_toolset_20260401"}],
319-
packages={"pip": ["pandas", "numpy"]},
320-
networking={"type": "unrestricted"},
321-
)
322-
"""
323-
# ── Agent fields ──
324-
name: str = "PraisonAI Managed Agent"
325-
model: str = "claude-sonnet-4-6"
326-
system: str = "You are a helpful AI assistant."
327-
tools: List[Dict[str, Any]] = field(default_factory=lambda: [{"type": "agent_toolset_20260401"}])
328-
mcp_servers: List[Dict[str, Any]] = field(default_factory=list)
329-
skills: List[Dict[str, Any]] = field(default_factory=list)
330-
callable_agents: List[Dict[str, Any]] = field(default_factory=list)
331-
metadata: Dict[str, Any] = field(default_factory=dict)
332-
333-
# ── Environment fields ──
334-
env_name: str = "praisonai-env"
335-
packages: Optional[Dict[str, List[str]]] = None
336-
networking: Dict[str, Any] = field(default_factory=lambda: {"type": "unrestricted"})
337-
338-
# ── Session fields ──
339-
session_title: str = "PraisonAI session"
340-
resources: List[Dict[str, Any]] = field(default_factory=list)
341-
vault_ids: List[str] = field(default_factory=list)
342-
343-
344305
@runtime_checkable
345306
class ManagedBackendProtocol(Protocol):
346307
"""Protocol for external managed agent backends.
@@ -354,7 +315,7 @@ class ManagedBackendProtocol(Protocol):
354315
355316
Lifecycle::
356317
357-
backend = SomeManagedBackend(config=ManagedBackendConfig(...))
318+
backend = SomeManagedBackend(config={...})
358319
agent = Agent(name="coder", backend=backend)
359320
result = agent.start("Write a script") # delegates to backend.execute()
360321
@@ -429,6 +390,46 @@ def reset_all(self) -> None:
429390
"""
430391
...
431392

393+
# ── Optional methods (default no-ops for backward compat) ──
394+
395+
def update_agent(self, **kwargs) -> None:
396+
"""Update an existing managed agent's configuration.
397+
398+
Allows changing system prompt, tools, model, etc. on a previously
399+
created agent without recreating it.
400+
401+
Args:
402+
**kwargs: Fields to update (system, tools, model, name, etc.).
403+
"""
404+
...
405+
406+
def interrupt(self) -> None:
407+
"""Send a user interrupt to the active session.
408+
409+
Signals the managed agent to stop its current work (equivalent to
410+
``user.interrupt`` event in the Anthropic API).
411+
"""
412+
...
413+
414+
def retrieve_session(self) -> Dict[str, Any]:
415+
"""Retrieve the current managed session's metadata and usage.
416+
417+
Returns:
418+
Dict with session info (id, status, usage, etc.).
419+
"""
420+
...
421+
422+
def list_sessions(self, **kwargs) -> List[Dict[str, Any]]:
423+
"""List sessions for the current agent.
424+
425+
Args:
426+
**kwargs: Provider-specific filters (limit, status, etc.).
427+
428+
Returns:
429+
List of session summary dicts.
430+
"""
431+
...
432+
432433

433434
__all__ = [
434435
'AgentProtocol',
@@ -440,5 +441,4 @@ def reset_all(self) -> None:
440441
'HttpLauncherProtocol',
441442
'McpLauncherProtocol',
442443
'ManagedBackendProtocol',
443-
'ManagedBackendConfig',
444444
]

src/praisonai-agents/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "praisonaiagents"
7-
version = "1.5.147"
7+
version = "1.5.148"
88
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
99
readme = "README.md"
1010
requires-python = ">=3.10"

0 commit comments

Comments
 (0)