Files
414c3bd104 fix(code): stop praisonai code truncating mid-task and reporting success (#4930)
* fix(code): stop `praisonai code` truncating mid-task and reporting success

Four linked defects meant `praisonai code` could not finish a coding task,
and nothing could tell that it hadn't. All four were reproduced end-to-end
before being changed; each fix has a named test that fails without it
(16/16 mutations killed).

(b) A truncated run reported success. `_run_print_code` classified any
    non-empty string as `status: "ok"`, exit 0 — but a budget-exhausted turn
    returns a non-empty wrap-up summary, so truncation was indistinguishable
    from completion. Measured before:
      $ praisonai code -p --output json "...make the tests pass"
      {"result": "Tool call limit reached (10 calls)...", "status": "ok"}   exit 0
      $ pytest -q  ->  6 failed, 2 passed
    Now `status: "truncated"` and exit 2, reusing `run._run_was_truncated`
    rather than adding a second, drifting guard. Same run after: exit 2.

(c) `--dangerously-skip-approval` did not skip approval. It set
    PRAISON_APPROVAL_MODE/PRAISONAI_TOOL_SAFETY, which the gate that actually
    prompts (the core `@require_approval` decorator, resolving through the
    approval registry backend) never reads. With stdin at /dev/null every
    prompt was auto-denied, so the agent could not run one shell command —
    while still exiting 0. Measured on one task, stdin /dev/null:
    before 2 prompts / 2 denials / `1 failed`; after 0 / 0 / `1 passed`.
    Fixed by registering AutoApproveBackend the way `--plan` already
    registers its own backend — one mechanism, not a second env var. Strictly
    opt-in: the safe-by-default branch is unchanged and now also clears a
    bypass left by an earlier --no-safe call in the same process. A per-agent
    backend (`--plan`, `--agent` scope) still wins, and --plan remains
    mutually exclusive with the opt-outs; both are covered by tests.

(a) The step budget was general-purpose, not coding-sized, and unreachable
    from the CLI. Two loops enforce different knobs — the LiteLLM loop caps at
    `max_tool_calls_per_turn=10` (Gemini-routed run stopped at exactly 10
    calls), the OpenAI-native loop at `max_steps`/`max_iter=20` — and
    `praisonai code` set neither. Ten calls is "list files, read two files,
    one grep"; it cannot reach a test run. Adds `--max-steps` (env fallback
    PRAISONAI_CODE_MAX_STEPS) defaulting to 200 for a coding session, raising
    *both* knobs, applied to the headless and interactive paths. The core
    ExecutionConfig defaults are deliberately left alone so no library user's
    behaviour changes. End-to-end on the 8-module repro: previously 6 failed /
    2 passed with `status: "ok"`; now 8 passed.

    Also fixes the remediation text at run.py:168, which told users to
    "Re-run with a higher --max-iter" — a flag with 0 occurrences in the CLI
    (control: `--model` = 56).

(d) The gate that would have caught all of this has been red for months. The
    Terminal-Bench smoke workflow pinned Python 3.11; harbor requires >=3.12,
    so `pip install harbor` resolved to no candidate and every scheduled run
    died in ~15s (confirmed 2026-07-27 through 2026-09-07, every week).
    RESULTS.md still says `_pending first run_`, accurately: no
    Terminal-Bench score has ever been produced. Bumped to 3.12 (verified:
    harbor 0.22.0 resolves cleanly on 3.12) and dropped the `|| true` that
    would hide a real harness failure. The first honest run may well be red —
    that is the point.

Refs #3932

Co-Authored-By: Claude Opus 5 <[email protected]>

* fix(code): apply --max-steps budget on profiled and wrapper-dispatched paths

Closes two Greptile P1 gaps in PR #4930 where the new coding step budget
was silently dropped:

- --profile/--profile-deep built the Agent with no ExecutionConfig, so a
  profiled coding run kept the general-purpose core defaults (20 steps /
  10 tool calls per turn). Thread build_code_execution_config(max_steps)
  into _run_profiled_code.
- The wrapper legacy dispatch (_run_chat_mode / _start_interactive_mode)
  never read args.execution, so the common `pip install praisonai`
  interactive/single-prompt sessions ignored --max-steps. Thread
  args.execution onto the Agent in both interactive_legacy build sites,
  mirroring the existing args.agent_approval pattern.

Adds regression tests locking in both paths.

🤖 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]>
2026-09-07 13:07:03 +01:00
..

Terminal-Bench 2.1 Integration with PraisonAI

This directory contains adapters for benchmarking PraisonAI on Terminal-Bench 2.1 via the Harbor framework. Everything lives in the examples/benchmark layer + CI — there are zero changes to the praisonaiagents / praisonai SDK surface.

Overview

Terminal-Bench 2.1 is the current release of the Laude Institute benchmark for evaluating AI coding agents in real terminal environments. The Harbor framework is the official evaluation harness that abstracts container lifecycle, parallelization, and cloud providers.

Setup

Install Harbor and PraisonAI into one venv and run from the repo root with PYTHONPATH=. so the adapter import path resolves:

pip install harbor
pip install -e src/praisonai-agents -e src/praisonai
export PYTHONPATH=.

Integration Types

0. Code Agent (headline — benchmarks praisonai code)

  • File: praisonai_code_agent.py
  • Purpose: Installs and drives the terminal-native praisonai code assistant headlessly inside the container.
  • Run:
    PYTHONPATH=. harbor run -d terminal-bench/terminal-bench-2-1 \
      --agent "examples.terminal_bench.praisonai_code_agent:PraisonAICodeAgent" \
      -m openai/gpt-4o-mini \
      --ae OPENAI_API_KEY=$OPENAI_API_KEY \
      -n 4
    

1. External Agent (Direct Agent Class)

  • File: praisonai_external_agent.py
  • Purpose: External agent that uses direct Agent() class instantiation
  • Usage: Run with --agent "module:Class"
  • Approach: Uses praisonaiagents.Agent directly with a bash tool bridged to Harbor's exec()

2. Wrapper Agent (CLI-Based)

  • File: praisonai_wrapper_agent.py
  • Purpose: Uses praisonai "TASK" CLI pattern instead of direct Agent class
  • Usage: Run with --agent-import-path examples.terminal_bench.praisonai_wrapper_agent:PraisonAIWrapperAgent
  • Approach: Installs praisonai CLI inside container and runs tasks via subprocess
  • Best for: Users who prefer CLI-style interface matching standard praisonai usage

3. Installed Agent (Production)

  • File: praisonai_installed_agent.py
  • Purpose: Production-ready agent installed inside Harbor containers
  • Usage: Integrates with Harbor's leaderboard system

Quick Start

Prerequisites

# Install Harbor framework
pip install harbor

# Install PraisonAI with shell tools
pip install praisonaiagents[tools]

Running External Agent (Direct Agent Class)

# Test with oracle agent first
harbor run -d terminal-bench/terminal-bench-2-1 -a oracle

# Run PraisonAI external agent (uses direct Agent() class)
PYTHONPATH=. harbor run -d terminal-bench/terminal-bench-2-1 \
  --agent "examples.terminal_bench.praisonai_external_agent:PraisonAIExternalAgent" \
  --model openai/gpt-4o-mini \
  --ae OPENAI_API_KEY=$OPENAI_API_KEY \
  -n 4

Running Wrapper Agent (CLI-Based)

# Run PraisonAI wrapper agent (uses `praisonai "TASK"` CLI pattern)
PYTHONPATH=. harbor run -d terminal-bench/terminal-bench-2-1 \
  --agent "examples.terminal_bench.praisonai_wrapper_agent:PraisonAIWrapperAgent" \
  --model openai/gpt-4o-mini \
  --ae OPENAI_API_KEY=$OPENAI_API_KEY \
  -n 4

Running on Cloud (Daytona/E2B/Modal)

PYTHONPATH=. harbor run -d terminal-bench/terminal-bench-2-1 \
  --agent "examples.terminal_bench.praisonai_external_agent:PraisonAIExternalAgent" \
  --model openai/gpt-4o-mini \
  --env daytona -n 32 \
  --ae OPENAI_API_KEY=$OPENAI_API_KEY

Key Features

  • Shell Execution Bridge: Wraps Harbor's BaseEnvironment.exec() as PraisonAI tool
  • Auto-Approval: Bypasses @require_approval for container-isolated execution
  • Token Tracking: Populates Harbor's AgentContext with usage metrics
  • API Key Forwarding: Supports environment variable injection
  • Multi-Agent Support: Can run AgentTeam and AgentFlow workflows

Architecture

┌─────────────────────────────────────────┐
│            Harbor Framework             │
│   (Terminal-Bench 2.0 Evaluation)      │
├─────────────────────────────────────────┤
│  BaseEnvironment.exec() ←→ bash_tool    │
├─────────────────────────────────────────┤
│         PraisonAI Agent                 │
│  • Uses execute_command tool            │
│  • Auto-approval for container safety  │
│  • Token tracking and metrics          │
└─────────────────────────────────────────┘

Files

  • README.md - This documentation
  • praisonai_code_agent.py - Headline adapter benchmarking praisonai code
  • job_code_smoke.yaml - Smoke-test job config for the code agent
  • RESULTS.md - Recorded pass-rates
  • praisonai_external_agent.py - External agent (direct Agent class)
  • praisonai_wrapper_agent.py - Wrapper agent (CLI-based approach)
  • praisonai_installed_agent.py - Installed agent implementation
  • multi_agent_example.py - Multi-agent team example
  • job.yaml - Example Harbor job configuration
  • test_basic.py - Basic smoke tests
  • test_integration.py - Integration tests
  • test_real_agentic.py - Real agentic tests

Terminal-Bench 2.0 Tasks

The benchmark includes 89 carefully curated tasks covering:

  • Compiling code
  • Training models
  • Setting up servers
  • System administration
  • File manipulation
  • Package management

Each task provides:

  • English instruction
  • Docker container environment
  • Test script (writes reward to /logs/verifier/reward.txt)
  • Reference oracle solution

Contributing

  1. Test changes with oracle agent first: harbor run -d terminal-bench/terminal-bench-2-1 -a oracle
  2. Run real agentic tests to ensure end-to-end functionality
  3. Follow PraisonAI's AGENTS.md architecture guidelines
  4. Add both unit tests and integration tests

Resources