* fix(mobile): Settings offers Remove only when there is a key, and refuses a bad address Four defects, all on the Settings screen, all seen on a device running main. 1. REMOVE WAS OFFERED WITH NOTHING TO REMOVE. The OpenAI key row read "Not set" and a `Remove` button sat under it -- a control that destroys nothing and reports nothing, which is the defect class this package spent two days eliminating everywhere else, surviving in the screen that introduced it. `canClear` is now computed in the view model (`state === "configured"`, not `!== "not-set"`: an UNRESOLVED keychain lookup is not a key), and the presence refresh flips the button in the SAME pass that repaints the word, so the two cannot disagree. 2. THE ENGINE ADDRESS RENDERED AS IF IT APPLIED WHEN IT COULD NOT. Its own help said "Only used by the remote engine" while it accepted edits under the in-process engine, which runs on the device and never contacts an address. `SettingDef.appliesWhen` lets the REGISTRY say which setting switches another on; the field is now disabled with "Set Engine to remote-http to use this." Disabled rather than hidden, and it is a close call. A field that disappears takes the typed value off the screen with it -- the store keeps it, but the user cannot see that it is kept, and someone flipping between engines watches their address vanish and come back. And an address is what a user looks for BEFORE choosing the engine that uses it: a row that is not there cannot teach that the two are connected. A test pins the round trip: type an address, switch to in-process, switch back, and it is still there. 3. A MALFORMED ADDRESS WAS ACCEPTED IN SILENCE. `7.0.0.1:8765` was stored, displayed back, and discovered to be wrong only when a turn failed. The refusal PATH has existed since #4694 (validateInput -> set -> a `role="alert"` note beside the field); what was missing is that `baseUrl` had no `validate` at all, so nothing was ever handed to it to refuse. `httpUrl()` in core/settings/store.ts is that half. It refuses everything `new URL` will not parse AND every scheme that is not http(s) -- so `localhost:8765`, which parses as a URL whose protocol is `localhost:`, does not slip through -- and it normalises what it accepts, so one engine is not three settings that differ by a trailing slash. The message names an address that WOULD work, because naming only the setting leaves the user looking at the same string with no idea which part was wrong. 4. THE CREDENTIAL WAS FILED UNDER "ENGINE". It is not an engine setting, it is the one field that decides whether the app answers at all, and it sat third of three at the same weight as a picker and an address. It now leads the screen in a section of its own. Registry order IS screen order, so the move is the whole of the reordering; `data-lead` marks the first section so the stylesheet can give it weight without the renderer knowing which one it is. app.css styled `.section-heading` while the app paints `.settings-section`, so every heading had been rendering at the browser's default h3 -- fixed, on the class the app actually emits. Also: every def has carried `help` since the registry was written and NOTHING rendered it. The screen painted a label, a control and a refusal note and dropped the sentence explaining what the field is for -- the same defect as an inert setting, one layer along. It is on screen now. Gates: each of the four defects, reintroduced, kills a named test -- offering Remove with no key, disabling the address under the remote engine, dropping the validator, and moving the key back under "Engine". Both the first PAINT and the later sync walk are covered; a renderer corrected only by the sync passed every end-to-end test while painting the defect. Verified on an Android 15 emulator, light and dark: no key (no Remove), key set (Remove offered and working), in-process (address off, with the sentence that turns it on), remote (address live), `7.0.0.1:8765` refused on screen, `http://10.0.0.7:9000/` accepted and normalised. Co-Authored-By: Claude Opus 5 <[email protected]> * fix(mobile): reject query/fragment engine addresses and associate settings help via aria-describedby httpUrl() preserved url.search, but the remote-http engine builds `${base}/chat` by concatenation, so a stored "http://host:8765/?token=abc" became "http://host:8765/?token=abc/chat" -- a request for "/" with a mangled query that reaches no endpoint, while Settings reported a successful save. Reject any address carrying a query or fragment at the point of acceptance. Help and inactive notes were visual siblings of their controls but not programmatically associated, so a screen-reader user heard only the field's aria-label. Give the notes stable ids and point the control's aria-describedby at them, keeping the inactive id in step with the disabled state in syncSettings. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Mervin Praison <[email protected]> --------- Co-authored-by: Claude Opus 5 <[email protected]> Co-authored-by: praisonai-triage-agent[bot] <272766704+praisonai-triage-agent[bot]@users.noreply.github.com> Co-authored-by: Mervin Praison <[email protected]>
PraisonAI 🦞 — Hire a 24/7 AI Workforce. Stop writing boilerplate and start shipping autonomous, self-improving agents that research, plan, and execute tasks across your apps. From one agent to an entire organization, deployed in 5 lines of code.
curl -fsSL https://praison.ai/install.sh | bash
██████╗ ██████╗ █████╗ ██╗███████╗ ██████╗ ███╗ ██╗ █████╗ ██╗
██╔══██╗██╔══██╗██╔══██╗██║██╔════╝██╔═══██╗████╗ ██║ ██╔══██╗██║
██████╔╝██████╔╝███████║██║███████╗██║ ██║██╔██╗ ██║ ███████║██║
██╔═══╝ ██╔══██╗██╔══██║██║╚════██║██║ ██║██║╚██╗██║ ██╔══██║██║
██║ ██║ ██║██║ ██║██║███████║╚██████╔╝██║ ╚████║ ██║ ██║██║
╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝
pip install praisonai
🎯 Use Cases
AI agents solving real-world problems across industries:
| Use Case | Description |
|---|---|
| 🔍 Research & Analysis | Conduct deep research, gather information, and generate insights from multiple sources automatically |
| 💻 Code Generation | Write, debug, and refactor code with AI agents that understand your codebase and requirements |
| ✍️ Content Creation | Generate blog posts, documentation, marketing copy, and technical writing with multi-agent teams |
| 📊 Data Pipelines | Extract, transform, and analyze data from APIs, databases, and web sources automatically |
| 🤖 Customer Support | Deploy 24/7 support bots on Telegram, Discord, Slack with memory and knowledge-backed responses |
| ⚙️ Workflow Automation | Automate multi-step business processes with agents that hand off tasks, verify results, and self-correct |
🚀 Meet your first Agent (Under 1 Minute)
- Install the lightweight core SDK:
pip install praisonaiagents
export OPENAI_API_KEY="your-api-key"
- Run your first autonomous agent:
from praisonaiagents import Agent
# Give your agent a goal, and watch it work.
agent = Agent(instructions="You are a senior data analyst.")
agent.start("Analyze the top 3 tech trends of 2026 and format as a markdown table.")
🧬 The Five-Layer Agent Stack
Most frameworks hand you one or two layers and leave the rest as homework. PraisonAI covers all five — plus the outer layer that decides where your agent actually runs.
Each layer wraps the one inside it. When an agent misbehaves, the layer tells you where to look.
┌─────────────────────────────────────────────────────────────────┐
│ ⬡ MANAGED AGENTS — Where does it actually run? │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 5 · GRAPH — Who runs when, and who checks whom? │ │
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
│ │ │ 4 · LOOP — When do we stop? │ │ │
│ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │
│ │ │ │ 3 · HARNESS — Can it act, and be checked? │ │ │ │
│ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ 2 · CONTEXT — Is the right thing in the window? │ │ │ │ │
│ │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │ │
│ │ │ │ │ │ 1 · PROMPT — Did I say it clearly? │ │ │ │ │ │
│ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ │
│ │ │ │ └─────────────────────────────────────────────────┘ │ │ │ │
│ │ │ └─────────────────────────────────────────────────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
| Layer | The question it answers | PraisonAI |
|---|---|---|
| 1 · Prompt | Did I say it clearly? | instructions=, role/goal/backstory, output=, templates= |
| 2 · Context | Is the right thing in the window? | memory=, knowledge=, context=, handoff ContextPolicy |
| 3 · Harness | Can it act, and be checked? | tools=, MCP(), guardrails=, approval=, hooks=, sandbox= |
| 4 · Loop | When do we stop? | execution=ExecutionConfig(...), reflection=, autonomy=, doom-loop detection |
| 5 · Graph | Who runs when, and who checks whom? | AgentFlow, route(), parallel(), loop(), repeat() |
| ⬡ Managed | Where does it actually run? | tools_run_on="docker" — one shared sandbox for the tools, or run_on="anthropic" for the whole agent |
Layer 1 · Prompt — Did I say it clearly?
Role, instructions, examples, output format.
from praisonaiagents import Agent
agent = Agent(
role="Senior Data Analyst",
goal="Turn raw numbers into decisions",
output="verbose", # markdown-formatted output
)
agent.start("Summarise Q3 revenue trends")
Layer 2 · Context — Is the right thing in the window?
Write, select, compress, isolate — the four context operations, one parameter each.
from praisonaiagents import Agent
agent = Agent(
instructions="You are a support engineer.",
memory={"user_id": "u-42"}, # write — persists across runs (needs a user_id)
knowledge=["docs/"], # select — retrieves only what's relevant
context="summarize", # compress — auto-compacts before the limit
)
Isolate is
handoffs=[specialist]— a sub-agent inherits the last few messages and the intersection of your tools, not your whole transcript. 📖 Handoffs
Layer 3 · Harness — Can it act, and be checked?
Agent = Model + Harness. Tool dispatch, plus the guides that steer before acting and the sensors that observe after.
from praisonaiagents import Agent, MCP, tool
@tool
def deploy(env: str) -> str:
"""Deploy the current build to an environment."""
return f"Deployed to {env}"
agent = Agent(
name="ReleaseEngineer",
instructions="You are a release engineer.",
tools=[deploy, MCP("npx -y @modelcontextprotocol/server-filesystem /tmp")],
approval=True, # guide — human gate before risky tools run
)
agent.start("Deploy to staging, then list the files you can read")
Layer 4 · Loop — When do we stop?
Hard iteration caps, budget ceilings, no-progress detection and completion checks — every brake is explicit.
from praisonaiagents import Agent, ExecutionConfig
agent = Agent(
instructions="Fix the failing tests.",
execution=ExecutionConfig(max_iter=30, max_budget=0.50, on_budget_exceeded="stop"),
autonomy=True, # required to drive the loop with run_autonomous()
)
result = agent.run_autonomous("Refactor the auth module", max_iterations=5)
print(result.completion_reason)
# goal | no_tool_calls | max_iterations | timeout | doom_loop | needs_help | error
# (with on_budget_exceeded="stop", hitting the cap raises BudgetExceededError,
# surfaced here as completion_reason="error")
Doom-loop detection is on by default. Repeated identical tool calls and A→B→A→B oscillation get caught — while a poller whose output keeps changing does not. 📖 Doom Loop Detection
Layer 5 · Graph — Who runs when, and who checks whom?
Topology as a versionable artifact: prompt chaining, routing, parallelisation, orchestrator-worker.
from praisonaiagents import AgentFlow
from praisonaiagents.workflows import route, parallel, repeat
flow = AgentFlow(steps=[
classifier,
route({"bug": [bug_agent], "feature": [feature_agent], "default": [triage]}),
parallel([reviewer, tester]), # fan out, join automatically
repeat(editor, until=lambda ctx: "approved" in ctx.previous_result.lower(),
max_iterations=3), # evaluator–optimizer
])
flow.run("Ticket #123: login fails on Safari")
The same graph is expressible in YAML with no Python at all. 📖 AgentFlow
⬡ Outside the stack: Managed Agents — Where does it actually run?
The harness is commoditising; where the agent executes is the next multiplier. Rather than burning your laptop's CPU, hand an agent a short-lived cloud sandbox — repo, tools and tests run there.
pip install praisonai
The simplest way in is tools_run_on= — one whole team or workflow shares one sandbox, so a file written by step 1 is there for step 2. Thinking stays on your machine:
from praisonaiagents import Agent, AgentFlow
writer = Agent(name="Writer", instructions="You write files.")
reader = Agent(name="Reader", instructions="You read files.")
flow = AgentFlow(tools_run_on="docker", steps=[writer, reader]) # or e2b | modal | daytona | flyio
flow.run("Write 'hello' to /workspace/note.txt, then read it back")
Same thing with no Python at all:
name: remote-demo
tools_run_on: docker # every step shares one sandbox
agents:
writer: {role: Writer, goal: Write files}
reader: {role: Reader, goal: Read files}
steps:
- agent: writer
action: "Write 'hello' to /workspace/note.txt"
- agent: reader
action: "Read /workspace/note.txt"
For a single agent, two words cover it — and they answer different questions:
from praisonaiagents import Agent
# A. Only the TOOLS move. Thinking stays on your machine.
agent = Agent(name="builder", instructions="You build things.",
tools_run_on="docker") # docker | e2b | modal | daytona | flyio
# tenki | sandlock | ssh | novita | subprocess
# B. The WHOLE agent moves — model calls, loop and tools
agent = Agent(name="teacher", instructions="You teach.", run_on="anthropic") # hosted
agent = Agent(name="builder", instructions="You build.", run_on="docker") # self-hosted
agent.start("Write a Python script that prints the first 10 primes, then run it")
Ask any object where it runs, and it will tell you:
>>> Agent(name="builder", instructions="x", tools_run_on="docker")
Agent(name='builder', thinks_on='this machine', tools_run_on='a Docker container')
>>> agent.where_does_it_run()
Thinking (the AI model calls) happens on this machine.
Tools run on a Docker container.
Your own tools (check_db) still run on this machine -- only shell, file and
code tools move. They read and write this machine's files.
Naming a place that cannot do the job is a typo, not a preference, so it says so:
>>> Agent(name="x", instructions="i", run_on="e2b")
TypeError: Agent(run_on='e2b') is not valid: run_on= places the whole agent
-- model calls, loop and tools -- on a managed runtime, and 'e2b' runs
commands but cannot host an agent loop.
To run only the tools there: Agent(tools_run_on='e2b')
To run one block of code somewhere else, name the place on that call:
agent.execute_code_sync("print(6 * 7)", run_in="sandlock") # kernel-enforced
See what is running and reclaim strays:
praisonai managed ps # list running sandboxes
praisonai managed stop --all # reclaim them
Sandboxes shut themselves down when idle (auto_shutdown, idle_timeout_s), and a post-setup snapshot is reused so the next run skips the image pull and dependency install. Commit a .praisonai/environment.yaml and the environment travels with the repo.
📖 20 runnable examples · manage sessions with
praisonai managed sessions list <agent-id>orpraisonai managed sessions resume <session-id> "<prompt>"
Stack framing adapted from The Five-Layer Agent Stack and Agent Harnesses vs Orbs.
🌌 The PraisonAI Ecosystem
Start simple with the core SDK, or expand to full visual builders and dashboards when you're ready.
- Core SDK (
praisonaiagents): For pure Python development.pip install praisonaiagents - 💻 PraisonAI CLI (
praisonai): For terminal-based developers.pip install praisonai - 🦞 Claw Dashboard: Connect agents directly to Telegram, Slack, or Discord.
pip install "praisonai[claw]" - 🔗 Flow Visual Builder: Drag-and-drop workflow creation.
pip install "praisonai[flow]" - 🤖 PraisonAI UI: Clean chat interface.
pip install "praisonai[ui]"
JavaScript SDK
npm install praisonai
🧠 Supported Providers & Features
Powered by 100+ LLMs (OpenAI, Anthropic, Gemini & local models).
View all 24 providers with examples
| Provider | Example |
|---|---|
| OpenAI | Example |
| Anthropic | Example |
| Google Gemini | Example |
| Ollama | Example |
| Groq | Example |
| DeepSeek | Example |
| xAI Grok | Example |
| Mistral | Example |
| Cohere | Example |
| Perplexity | Example |
| Fireworks | Example |
| Together AI | Example |
| OpenRouter | Example |
| HuggingFace | Example |
| Azure OpenAI | Example |
| AWS Bedrock | Example |
| Google Vertex | Example |
| Databricks | Example |
| Cloudflare | Example |
| AI21 | Example |
| Replicate | Example |
| SageMaker | Example |
| Moonshot | Example |
| vLLM | Example |
"Grok 3 customer support" — Elon Musk quoting PraisonAI's tutorial
🌟 Why PraisonAI?
| Feature | How | |
|---|---|---|
| 🔌 | MCP Protocol — stdio, HTTP, WebSocket, SSE | tools=MCP("npx ...") |
| 🧠 | Planning Mode — plan → execute → reason | planning=True |
| 🔍 | Deep Research — multi-step autonomous research | Docs |
| 🤖 | External Agents — orchestrate Claude Code, Gemini CLI, Codex | Docs |
| 🔄 | Agent Handoffs — seamless conversation passing | handoffs=[other_agent] |
| 🛡️ | Guardrails — input/output validation | Docs |
| Web Search + Fetch — native browsing | web=True |
|
| 🪞 | Self Reflection — agent reviews its own output | Docs |
| 🔀 | Workflow Patterns — route, parallel, loop, repeat | Docs |
| 🧠 | Memory (zero deps) — works out of the box | memory=True |
View all 25 features
| Feature | How | |
|---|---|---|
| 💡 | Prompt Caching — reduce latency + cost | caching=True |
| 💾 | Sessions + Auto-Save — persistent state across restarts | auto_save="my-project" |
| 💭 | Thinking Budgets — control reasoning depth | agent.thinking_budget = 1024 |
| 📚 | RAG + Quality-Based RAG — auto quality scoring retrieval | Docs |
| 📊 | Model Router — auto-routes to cheapest capable model | Docs |
| 🧊 | Shadow Git Checkpoints — auto-rollback on failure | Docs |
| 📡 | A2A Protocol — agent-to-agent interop | Docs |
| 📏 | Context Compaction — never hit token limits | Docs |
| 📡 | Telemetry — OpenTelemetry traces, spans, metrics | Docs |
| 📜 | Policy Engine — declarative agent behavior control | Docs |
| 🔄 | Background Tasks — fire-and-forget agents | Docs |
| 🔁 | Doom Loop Detection — auto-recovery from stuck agents | Docs |
| 🕸️ | Graph Memory — Neo4j-style relationship tracking | Docs |
| 🏖️ | Sandbox Execution — isolated code execution | Docs |
| 🖥️ | Bot Gateway — multi-agent routing across channels | Docs |
📘 Using Python Code
1. Single Agent
from praisonaiagents import Agent
agent = Agent(instructions="You are a helpful AI assistant")
agent.start("Write a movie script about a robot in Mars")
2. Multi Agents
from praisonaiagents import Agent, Agents
research_agent = Agent(instructions="Research about AI")
summarise_agent = Agent(instructions="Summarise research agent's findings")
agents = Agents(agents=[research_agent, summarise_agent])
agents.start()
3. MCP (Model Context Protocol)
from praisonaiagents import Agent, MCP
# stdio - Local NPX/Python servers
agent = Agent(tools=MCP("npx @modelcontextprotocol/server-memory"))
# Streamable HTTP - Production servers
agent = Agent(tools=MCP("https://api.example.com/mcp"))
# WebSocket - Real-time bidirectional
agent = Agent(tools=MCP("wss://api.example.com/mcp", auth_token="token"))
# With environment variables
agent = Agent(
tools=MCP(
command="npx",
args=["-y", "@modelcontextprotocol/server-brave-search"],
env={"BRAVE_API_KEY": "your-key"}
)
)
📖 Full MCP docs — stdio, HTTP, WebSocket, SSE transports
4. Custom Tools
from praisonaiagents import Agent, tool
@tool
def search(query: str) -> str:
"""Search the web for information."""
return f"Results for: {query}"
@tool
def calculate(expression: str) -> float:
"""Safely evaluate a numeric arithmetic expression."""
import ast
import operator
# Define allowed operations
_OPS = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
ast.Pow: operator.pow,
ast.USub: operator.neg,
ast.UAdd: operator.pos,
}
def _safe_eval(node):
if isinstance(node, ast.Constant) and isinstance(node.value, (int, float)):
return node.value
elif isinstance(node, ast.BinOp) and type(node.op) in _OPS:
return _OPS[type(node.op)](_safe_eval(node.left), _safe_eval(node.right))
elif isinstance(node, ast.UnaryOp) and type(node.op) in _OPS:
return _OPS[type(node.op)](_safe_eval(node.operand))
else:
raise ValueError("Unsupported expression")
try:
return _safe_eval(ast.parse(expression, mode="eval").body)
except (ValueError, SyntaxError, TypeError, ZeroDivisionError, OverflowError):
raise ValueError("Invalid arithmetic expression")
agent = Agent(
instructions="You are a helpful assistant",
tools=[search, calculate]
)
agent.start("Search for AI news and calculate 15*4")
⚠️ Security Note: Never use
eval(),exec(), orsubprocessin tool functions that process LLM-generated or user-supplied input. Always validate and sanitize inputs to prevent code injection attacks. 📖 Full tools docs — BaseTool, tool packages, 100+ built-in tools
5. Persistence (Databases)
from praisonaiagents import Agent, db
agent = Agent(
name="Assistant",
memory={
"db": db(database_url="postgresql://localhost/mydb"),
"session_id": "my-session",
},
)
agent.chat("Hello!") # Auto-persists messages, runs, traces
📖 Full persistence docs — PostgreSQL, MySQL, SQLite, MongoDB, Redis, and 20+ more
6. PraisonAI Claw 🦞 (Dashboard UI)
Connect your AI agents to Telegram, Discord, Slack, WhatsApp and more — all from a single command.
pip install "praisonai[claw]"
praisonai claw
Required Environment Variables
Copy .env.example to .env and configure the following variables:
| Variable | Required | Description |
|---|---|---|
OPENAI_API_KEY |
Yes | OpenAI API key for all LLM calls |
TAVILY_API_KEY |
Yes (Claw) | Tavily key for the built-in web-search tool. Get one free at https://app.tavily.com |
Open http://localhost:8082 — the dashboard comes with 13 built-in pages: Chat, Agents, Memory, Knowledge, Channels, Guardrails, Cron, and more. Add messaging channels directly from the UI.
📖 Full Claw docs — platform tokens, CLI options, Docker, and YAML agent mode
7. Langflow Integration 🔗 (Visual Flow Builder)
Build multi-agent workflows visually with drag-and-drop components in Langflow.
pip install "praisonai[flow]"
praisonai flow
Open http://localhost:7861 — use the Agent and Agent Team components to create sequential or parallel workflows. Connect Chat Input → Agent Team → Chat Output for instant multi-agent pipelines.
📖 Full Flow docs — visual agent building, component reference, and deployment
8. PraisonAI UI 🤖 (Clean Chat)
Lightweight chat interface for your AI agents.
pip install "praisonai[ui]"
praisonai ui
📄 Using YAML (No Code)
Example 1: Two Agents Working Together
Create agents.yaml:
framework: praisonai
topic: "Write a blog post about AI"
agents:
researcher:
role: Research Analyst
goal: Research AI trends and gather information
instructions: "Find accurate information about AI trends"
writer:
role: Content Writer
goal: Write engaging blog posts
instructions: "Write clear, engaging content based on research"
Run with:
praisonai agents.yaml
The agents automatically work together sequentially
Example 2: Agent with Custom Tool
Create two files in the same folder:
agents.yaml:
framework: praisonai
topic: "Calculate the sum of 25 and 15"
agents:
calculator_agent:
role: Calculator
goal: Perform calculations
instructions: "Use the add_numbers tool to help with calculations"
tools:
- add_numbers
tools.py:
def add_numbers(a: float, b: float) -> float:
"""
Add two numbers together.
Args:
a: First number
b: Second number
Returns:
The sum of a and b
"""
return a + b
Run with:
praisonai agents.yaml
💡 Tips:
- Use the function name (e.g.,
add_numbers) in the tools list, not the file name- Tools in
tools.pyare automatically discovered- The function's docstring helps the AI understand how to use it
🎯 CLI Quick Reference
| Category | Commands |
|---|---|
| Execution | praisonai, --auto, --interactive, --chat |
| Research | research, --query-rewrite, --deep-research |
| Planning | --planning, --planning-tools, --planning-reasoning |
| Workflows | workflow run, workflow list, workflow auto |
| Memory | memory show, memory add, memory search, memory clear |
| Knowledge | knowledge add, knowledge query, knowledge list |
| Sessions | session list, session resume, session delete |
| Tools | tools list, tools info, tools search |
| MCP | mcp list, mcp create, mcp enable |
| Development | commit, docs, checkpoint, hooks |
| Scheduling | schedule start, schedule list, schedule stop |
✨ Key Features
🤖 Core Agents
| Feature | Code | Docs |
|---|---|---|
| Single Agent | Example | 📖 |
| Multi Agents | Example | 📖 |
| Auto Agents | Example | 📖 |
| Self Reflection AI Agents | Example | 📖 |
| Reasoning AI Agents | Example | 📖 |
| Multi Modal AI Agents | Example | 📖 |
🔄 Workflows
| Feature | Code | Docs |
|---|---|---|
| Simple Workflow | Example | 📖 |
| Workflow with Agents | Example | 📖 |
Agentic Routing (route()) |
Example | 📖 |
Parallel Execution (parallel()) |
Example | 📖 |
Loop over List/CSV (loop()) |
Example | 📖 |
Evaluator-Optimizer (repeat()) |
Example | 📖 |
| Conditional Steps | Example | 📖 |
| Workflow Branching | Example | 📖 |
| Workflow Early Stop | Example | 📖 |
| Workflow Checkpoints | Example | 📖 |
💻 Code & Development
| Feature | Code | Docs |
|---|---|---|
| Code Interpreter Agents | Example | 📖 |
| AI Code Editing Tools | Example | 📖 |
| External Agents (All) | Example | 📖 |
| Claude Code CLI | Example | 📖 |
| Gemini CLI | Example | 📖 |
| Codex CLI | Example | 📖 |
| Cursor CLI | Example | 📖 |
🧠 Memory & Knowledge
| Feature | Code | Docs |
|---|---|---|
| Memory (Short & Long Term) | Example | 📖 |
| File-Based Memory | Example | 📖 |
| Claude Memory Tool | Example | 📖 |
| Add Custom Knowledge | Example | 📖 |
| RAG Agents | Example | 📖 |
| Chat with PDF Agents | Example | 📖 |
| Data Readers (PDF, DOCX, etc.) | CLI | 📖 |
| Vector Store Selection | CLI | 📖 |
| Retrieval Strategies | CLI | 📖 |
| Rerankers | CLI | 📖 |
| Index Types (Vector/Keyword/Hybrid) | CLI | 📖 |
| Query Engines (Sub-Question, etc.) | CLI | 📖 |
🔬 Research & Intelligence
| Feature | Code | Docs |
|---|---|---|
| Deep Research Agents | Example | 📖 |
| Query Rewriter Agent | Example | 📖 |
| Native Web Search | Example | 📖 |
| Built-in Search Tools | Example | 📖 |
| Unified Web Search | Example | 📖 |
| Web Fetch (Anthropic) | Example | 📖 |
📋 Planning & Execution
| Feature | Code | Docs |
|---|---|---|
| Planning Mode | Example | 📖 |
| Planning Tools | Example | 📖 |
| Planning Reasoning | Example | 📖 |
| Prompt Chaining | Example | 📖 |
| Evaluator Optimiser | Example | 📖 |
| Orchestrator Workers | Example | 📖 |
👥 Specialized Agents
| Feature | Code | Docs |
|---|---|---|
| Data Analyst Agent | Example | 📖 |
| Finance Agent | Example | 📖 |
| Shopping Agent | Example | 📖 |
| Recommendation Agent | Example | 📖 |
| Wikipedia Agent | Example | 📖 |
| Programming Agent | Example | 📖 |
| Math Agents | Example | 📖 |
| Markdown Agent | Example | 📖 |
| Prompt Expander Agent | Example | 📖 |
🎨 Media & Multimodal
| Feature | Code | Docs |
|---|---|---|
| Image Generation Agent | Example | 📖 |
| Image to Text Agent | Example | 📖 |
| Video Agent | Example | 📖 |
| Camera Integration | Example | 📖 |
🔌 Protocols & Integration
| Feature | Code | Docs |
|---|---|---|
| MCP Transports | Example | 📖 |
| WebSocket MCP | Example | 📖 |
| MCP Security | Example | 📖 |
| MCP Resumability | Example | 📖 |
| MCP Config Management | Docs | 📖 |
| LangChain Integrated Agents | Example | 📖 |
🛡️ Safety & Control
| Feature | Code | Docs |
|---|---|---|
| Guardrails | Example | 📖 |
| Human Approval | Example | 📖 |
| Rules & Instructions | Docs | 📖 |
⚙️ Advanced Features
| Feature | Code | Docs |
|---|---|---|
| Async & Parallel Processing | Example | 📖 |
| Parallelisation | Example | 📖 |
| Repetitive Agents | Example | 📖 |
| Agent Handoffs | Example | 📖 |
| Stateful Agents | Example | 📖 |
| Autonomous Workflow | Example | 📖 |
| Structured Output Agents | Example | 📖 |
| Model Router | Example | 📖 |
| Prompt Caching | Example | 📖 |
| Fast Context | Example | 📖 |
🛠️ Tools & Configuration
| Feature | Code | Docs |
|---|---|---|
| 100+ Custom Tools | Example | 📖 |
| YAML Configuration | Example | 📖 |
| 100+ LLM Support | Example | 📖 |
| Callback Agents | Example | 📖 |
| Hooks | Example | 📖 |
| Middleware System | Example | 📖 |
| Configurable Model | Example | 📖 |
| Rate Limiter | Example | 📖 |
| Injected Tool State | Example | 📖 |
| Shadow Git Checkpoints | Example | 📖 |
| Background Tasks | Example | 📖 |
| Policy Engine | Example | 📖 |
| Thinking Budgets | Example | 📖 |
| Output Styles | Example | 📖 |
| Context Compaction | Example | 📖 |
📊 Monitoring & Management
| Feature | Code | Docs |
|---|---|---|
| Sessions Management | Example | 📖 |
| Auto-Save Sessions | Docs | 📖 |
| History in Context | Docs | 📖 |
| Telemetry | Example | 📖 |
| Langfuse Tracing | Docs | 📖 |
| Project Docs (.praison/docs/) | Docs | 📖 |
| AI Commit Messages | Docs | 📖 |
| @Mentions in Prompts | Docs | 📖 |
🖥️ CLI Features
| Feature | Code | Docs |
|---|---|---|
| Slash Commands | Example | 📖 |
| Autonomy Modes | Example | 📖 |
| Cost Tracking | Example | 📖 |
| Repository Map | Example | 📖 |
| Interactive TUI | Example | 📖 |
| Git Integration | Example | 📖 |
| Sandbox Execution | Example | 📖 |
| CLI Compare | Example | 📖 |
| Profile/Benchmark | Docs | 📖 |
| Auto Mode | Docs | 📖 |
| Init | Docs | 📖 |
| File Input | Docs | 📖 |
| Final Agent | Docs | 📖 |
| Max Tokens | Docs | 📖 |
🧪 Evaluation
| Feature | Code | Docs |
|---|---|---|
| Accuracy Evaluation | Example | 📖 |
| Performance Evaluation | Example | 📖 |
| Reliability Evaluation | Example | 📖 |
| Criteria Evaluation | Example | 📖 |
💻 Using JavaScript Code
npm install praisonai
export OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxx
const { Agent } = require('praisonai');
const agent = new Agent({ instructions: 'You are a helpful AI assistant' });
agent.start('Write a movie script about a robot in Mars');
⚡ Performance
PraisonAI is built for speed, with agent instantiation in around 14μs. This reduces overhead, improves responsiveness, and helps multi-agent systems scale efficiently in real-world production workloads.
| Performance Metric | PraisonAI |
|---|---|
| Avg Instantiation Time | 14 μs |
⭐ Star History
* export TAVILY_API_KEY=xxxxx
🔍 Langfuse Tracing
pip install "praisonai[langfuse]"
praisonai langfuse
🎓 Video Tutorials
Learn PraisonAI through our comprehensive video series:
View all 22 video tutorials
👥 Contributing
We welcome contributions! Fork the repo, create a branch, and submit a PR → Contributing Guide.
❓ FAQ & Troubleshooting
ModuleNotFoundError: No module named 'praisonaiagents'
Install the package:
pip install praisonaiagents
API key not found / Authentication error
Ensure your API key is set:
export OPENAI_API_KEY=your_key_here
For other providers, see Models docs.
How do I use a local model (Ollama)?
# Start Ollama and pull a model
ollama serve
ollama pull llama3.2
from praisonaiagents import Agent
agent = Agent(instructions="You are a helpful assistant", llm="ollama/llama3.2")
agent.start("Why is the sky blue?")
The ollama/ prefix is what selects Ollama's handling — tool-call repair,
tool-result formatting and the streaming rules small local models need. Or set
it by environment instead:
export OPENAI_MODEL_NAME=ollama/llama3.2
Setting only OPENAI_BASE_URL is not enough: with no model named, the OpenAI
default (gpt-4o-mini) is sent to Ollama, which answers
404 model 'gpt-4o-mini' not found. Always name the model.
Point at a non-default host with base_url= or OLLAMA_HOST:
agent = Agent(instructions="...", llm="ollama/llama3.2", base_url="http://192.168.1.10:11434")
The same shape works for other local runtimes — lm_studio/, vllm/ and
hosted_vllm/ with their server's base_url.
See Models docs for more details.
How do I persist conversations to a database?
Use the db parameter:
from praisonaiagents import Agent, db
agent = Agent(
name="Assistant",
memory={
"db": db(database_url="postgresql://localhost/mydb"),
"session_id": "my-session",
},
)
See Persistence docs for supported databases.
How do I enable agent memory?
from praisonaiagents import Agent
agent = Agent(
name="Assistant",
# Enables file-based memory (no extra deps!)
memory={"user_id": "user123"},
)
See Memory docs for more options.
How do I run multiple agents together?
from praisonaiagents import Agent, Agents
agent1 = Agent(instructions="Research topics")
agent2 = Agent(instructions="Summarize findings")
agents = Agents(agents=[agent1, agent2])
agents.start()
See Agents docs for more examples.
How do I use MCP tools?
from praisonaiagents import Agent, MCP
agent = Agent(
tools=MCP("npx @modelcontextprotocol/server-memory")
)
See MCP docs for all transport options.
Getting Help
Made with ❤️ by the PraisonAI Team
📚 Documentation • GitHub • ▶️ YouTube • 𝕏 X • 💼 LinkedIn

























