CodeAgent

Agent that generates, executes, reviews and refactors code with a pluggable executor

CodeAgent generates, executes, reviews, and refactors code, and only runs code when you name an explicit executor.

Diagram

📝 Input

🤖 CodeAgent

generate

execute

review

refactor

✅ Output

Quick Start

  1. Run code with an explicit executor
    typescript
    import { CodeAgent, createSubprocessExecutor } from 'praisonai';
    
    const agent = new CodeAgent({
      name: 'Coder',
      code: {
        executor: createSubprocessExecutor(),   // opt-in real runner
        allowedLanguages: ['python'],
        timeout: 20,
      },
    });
    
    const result = await agent.execute('print(2 + 2)', 'python');
    console.log(result.output);   // "4\n"
    console.log(result.success);  // true
  2. Generate, review and refactor
    typescript
    const code = await agent.generate('Write a function to reverse a string');
    const review = await agent.review(code);
    const better = await agent.refactor(code, 'add type hints');

Why an explicit executor?

Execution is granted by naming a runner, never by flipping a boolean.

Without code.executor, execute() returns { success: false, error: 'No code executor is configured...' }. This is deliberate, so model-generated code cannot silently run in-process.

typescript
const agent = new CodeAgent({ name: 'Coder' }); // no executor

const result = await agent.execute('print(2 + 2)', 'python');
console.log(result.success); // false
console.log(result.error);   // "No code executor is configured, so 'python' code was not run. ..."

How It Works

Diagram
RunnerExecutorCodeAgentUserRunnerExecutorCodeAgentUserexecute(code, language)check allowedLanguagesrun(code, language, context)child process (cwd, env, timeout)stdout / stderr / exit codeCodeExecutionResult{ success, output, error }

CodeConfig

FieldTypeDefaultPurpose
executorCodeExecutor—The only way to make execute() actually run code.
sandboxbooleantrueAdvisory hint passed through to the executor. Does NOT gate execution.
timeoutnumber (seconds)30Kills the whole process tree on timeout (SIGKILL).
allowedLanguagesstring[]['python']Gate at the CodeAgent level.
maxOutputLengthnumber10000Output capped as chunks arrive (bounded memory).
workingDirectorystringprocess.cwd()Passed to the executor.
environmentRecord<string, string>{}Merged with process.env.

createSubprocessExecutor()

createSubprocessExecutor() is a ready-made out-of-process runner.

typescript
import { CodeAgent, createSubprocessExecutor } from 'praisonai';

const agent = new CodeAgent({
  code: { executor: createSubprocessExecutor() },
});

Default interpreter map:

LanguageInterpreter
python, python3process.env.PRAISONAI_PYTHON ?? 'python3' with -c
javascript, nodeprocess.execPath with -e
bashbash -c
shsh -c
  • Runs a detached child on non-Windows so the timeout kills the whole process group.
  • Truncates output live during streaming, not after close.
  • An unregistered language returns { success: false, error: "No interpreter is registered for '<lang>'. Known: ..." }.

Writing your own executor

Supply a CodeExecutor to target a container, microVM, e2b, or a remote sandbox service.

typescript
import { CodeAgent, type CodeExecutor, type CodeExecutorContext } from 'praisonai';

const remoteExecutor: CodeExecutor = async (code, language, context: CodeExecutorContext) => {
  // Send code to your container / microVM / remote sandbox
  return {
    success: true,
    output: '...',
    exitCode: 0,
    executionTime: 0.1,
  };
};

const agent = new CodeAgent({ code: { executor: remoteExecutor } });

The CodeExecutor signature:

typescript
type CodeExecutor = (
  code: string,
  language: string,
  context: CodeExecutorContext,
) => Promise<CodeExecutionResult>;

CodeExecutorContext carries sandbox, timeout, workingDirectory, environment, and maxOutputLength.


Best Practices

Name an executor explicitly

Never rely on a boolean to enable execution. Pass createSubprocessExecutor() or your own runner so execution is a visible decision.

Restrict allowed languages

Set allowedLanguages to only the languages you expect. execute() rejects any other language before the executor runs.

Isolate untrusted code

Supply a container or microVM executor for model-generated or user-supplied code. The subprocess runner shares the host.

Bound output and time

Keep maxOutputLength and timeout sensible. Output is capped as it streams and the timeout kills the whole process tree.


Related