Skip to main content

Persistent just-py-bash shell capability and toolset wrapper for Pydantic AI

Project description

pydantic-ai-just-bash

PyPI Python 3.11+ License: MIT

pydantic-ai-just-bash is a small extension package for Pydantic AI that gives an agent a persistent just-py-bash shell.

The extension exposes a bash tool plus helper tools like bash_list_tools, bash_search_tools, and bash_describe_tool, and binds wrapped Pydantic AI tools into that shell as commands.

By default, wrapped tools stay directly visible to the model as normal Pydantic AI tools. If you want a shell-only interface, set expose_wrapped_tools=False.

It is designed to let an agent mix shell workflows with normal Pydantic AI tool calls while keeping a long-lived virtual filesystem for the lifetime of the agent run.

Why use it?

  • Give an agent a persistent bash-like environment without a real OS shell
  • Expose normal Pydantic AI tools as shell commands
  • Keep deferred tools hidden until the model discovers them with shell-side search
  • Reuse just-py-bash session controls like files, env, cwd, fs, python, and javascript
  • Return structured execution results instead of raw subprocess plumbing

Install

Requires Python 3.11+

Use case Command
Install from PyPI with uv uv add pydantic-ai-just-bash
Install spec/YAML support too uv add 'pydantic-ai-just-bash[spec]'
Install from PyPI with pip pip install pydantic-ai-just-bash
Install a cloned checkout in editable mode pip install -e .

Install name: pydantic-ai-just-bash
Import name: pydantic_ai_just_bash

This package only adds the shell capability. Install whatever Pydantic AI model/provider extras you already need separately.

Quick start

from pydantic_ai import Agent
from pydantic_ai_just_bash import JustBash

agent = Agent(
    'openai:gpt-5.2',
    capabilities=[JustBash(python=True)],
)


@agent.tool_plain
def get_weather(city: str) -> str:
    """Get the weather for a city."""
    return f'Sunny in {city}'


@agent.tool_plain(defer_loading=True)
def stock_lookup(symbol: str) -> str:
    """Look up a stock price."""
    return f'{symbol}=150.00'

Inside bash, the model can do things like:

bash_list_tools
get_weather Paris
printf 'draft note' > note.txt
cat note.txt
bash_search_tools stock
stock_lookup AAPL

The shell session and virtual filesystem persist across bash calls for the lifetime of the agent run.

API overview

JustBash

Use JustBash as an agent capability. It wraps the assembled toolset and injects a bash tool plus bash helper tools.

from pydantic_ai_just_bash import JustBash

capability = JustBash(
    tool_name='bash',
    command_prefix='',
    helper_prefix='bash_',
    python=True,
)

Common configuration knobs include:

  • tool_name
  • command_prefix
  • helper_prefix
  • exposed_tools
  • expose_wrapped_tools
  • instructions
  • help_flag_name
  • rename_help_argument
  • files, env, cwd, fs, execution_limits
  • python, javascript, commands, network, process_info
  • node_command, js_entry, package_json

JustBashToolset

Use JustBashToolset if you want to wrap a specific toolset directly instead of using a capability.

from pydantic_ai import Agent, FunctionToolset
from pydantic_ai_just_bash import JustBashToolset

base = FunctionToolset()


@base.tool_plain
def echo(text: str) -> str:
    return text


agent = Agent('openai:gpt-5.2', toolsets=[JustBashToolset(base)])

Result models

The package exports structured result models for the public helper tools:

  • BashExecutionResult
  • BashListToolsResult
  • BashSearchToolsResult
  • BashDescribeToolResult
  • BashCommandInfo

Agent specs and YAML

JustBash can be loaded from Agent.from_spec(...) and Agent.from_file(...).

model: test
capabilities:
  - JustBash:
      tool_name: bash
      helper_prefix: bash_
      python: true
      files:
        /workspace/seed.txt: hello from spec
        /workspace/lazy.txt:
          provider: lazy content from spec

Use the spec extra if you want the package to carry the YAML/spec dependencies itself:

uv add 'pydantic-ai-just-bash[spec]'

Spec-safe configuration surface

The current spec-safe surface includes the public JustBash fields, including:

  • shell naming/config fields like tool_name, command_prefix, helper_prefix, instructions, help_flag_name, and expose_wrapped_tools
  • runtime/session fields like env, cwd, execution_limits, python, javascript, commands, network, process_info, node_command, js_entry, and package_json
  • filesystem configuration via files and fs
  • spec-friendly file values such as plain text/bytes, FileInit, and LazyFile with a static provider value
  • string-based rename_help_argument values

Python-only configuration surface

Some configuration remains Python-only because it depends on runtime callables rather than JSON/YAML data.

The current Python-only surface includes:

  • callable exposed_tools selectors
  • callback-based lazy file providers, either passed directly or wrapped in LazyFile(...)
  • callable rename_help_argument values

For example:

from just_bash import LazyFile
from pydantic_ai_just_bash import JustBash

cap = JustBash(
    files={
        '/workspace/generated.txt': LazyFile(provider=lambda: 'generated at session start\n'),
    },
)

That callable form is supported when you configure JustBash(...) in Python, but it is not spec/YAML-serializable.

Public helper tools

At the agent level, the wrapper exposes:

  • bash
  • bash_list_tools
  • bash_search_tools
  • bash_describe_tool

Inside the shell, the same helper concepts are available as commands:

  • bash_list_tools
  • bash_describe_tool <tool-or-command>
  • bash_call_tool <tool-or-command> --json '{...}'
  • bash_search_tools <keywords>

Tool visibility model

Wrapped tools remain directly visible to the model by default, so an agent can either call them normally or use them through bash.

If you want the model to go through the shell interface only, set:

JustBash(expose_wrapped_tools=False)

In shell-only mode, the model still sees bash, bash_list_tools, bash_search_tools, and bash_describe_tool, but the wrapped tools themselves are omitted from the public agent tool list.

Argument binding

Wrapped tools are still validated by Pydantic AI, but the shell adapter tries to behave like a small CLI layer first:

Form Example
Named flags for simple values my_tool --a 1 --b 2
Booleans with --flag / --no-flag my_tool --verbose --no-cache
Single positional value for single-argument tools get_weather Paris
-- to stop option parsing show_value -- --help
JSON object escape hatch my_tool --json '{"a": 1, "b": 2}'
JSON via stdin `echo '{"a": 1, "b": 2}'

Use shell-style flags for simple scalar values. Prefer --json or --stdin-json for objects, arrays, or anything that becomes awkward to quote safely.

When a command has multiple parameters, bare positional input is rejected with a CLI-style error that points back to --help and --json.

Use --help or -h on a bound command, or bash_describe_tool, to inspect generated command help, rendered signatures, renamed arguments, and JSON schema.

Help flag behavior

By default, shell-exposed commands reserve --help and -h for generated command help.

If a wrapped tool has a real argument named help, wrapper creation fails by default with a configuration error. This makes the collision explicit instead of silently changing command behavior.

You can override that behavior with:

  • help_flag_name='usage' to reserve a different help flag instead of --help
  • rename_help_argument=... to rename the wrapped tool's conflicting shell argument

For example:

JustBash(rename_help_argument='{tool_name}_{arg_name}')

would expose a tool argument named help as --<tool_name>_help in the shell, and generated help text will explain that rename explicitly.

Behavior notes

  • The shell session is persistent for a run, so virtual filesystem changes carry across bash calls.
  • Wrapped tools stay directly visible by default; set expose_wrapped_tools=False for shell-only mode.
  • The set of bound commands is captured on first shell use in a run. If wrapped tools change dynamically and you want a fresh command set, call bash(..., reset_session=True).
  • Deferred tools are hidden in the shell until discovered with bash_search_tools.
  • Shell command failures are formatted as CLI-style stderr messages instead of leaking raw framework internals where possible.
  • Direct shell commands return the tool result. If a wrapped tool returns ToolReturn, the shell uses its return_value.

Development

make install
make all-ci
uv build

Common commands:

Task Command
Install dev + lint tooling make install
Format code and config make format
Check formatting only make format-check
Lint make lint
Type-check make typecheck
Test make test
Run the full local CI suite make all-ci

Project status

This package is still early-stage and the public API may evolve as the shell command model settles. See ROADMAP.md.

Related projects

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pydantic_ai_just_bash-0.2.0.tar.gz (26.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pydantic_ai_just_bash-0.2.0-py3-none-any.whl (22.3 kB view details)

Uploaded Python 3

File details

Details for the file pydantic_ai_just_bash-0.2.0.tar.gz.

File metadata

  • Download URL: pydantic_ai_just_bash-0.2.0.tar.gz
  • Upload date:
  • Size: 26.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for pydantic_ai_just_bash-0.2.0.tar.gz
Algorithm Hash digest
SHA256 4b9e880e702ce4e670cdcf3c8ebfa48b38cf3c516b9bd49e4ea5266ae1d9ccea
MD5 ece0f6c4ad92718cfc54d289bc9260cf
BLAKE2b-256 2248e933d84bbd119e0ee030f69dec9554122e7c1fcd9ed151af2a8e7a88c150

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydantic_ai_just_bash-0.2.0.tar.gz:

Publisher: release.yml on nathan-gage/pydantic-ai-just-bash

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pydantic_ai_just_bash-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pydantic_ai_just_bash-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0c6700edf253d65ca5f1f0befe61c6005cc9edd50866ac9907c620d0617bff42
MD5 432ebf38ee9a759356dfa21f68604418
BLAKE2b-256 66b70d024c983c275422205f332ae724e2bc7b86877774171e5867dd578cd20e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pydantic_ai_just_bash-0.2.0-py3-none-any.whl:

Publisher: release.yml on nathan-gage/pydantic-ai-just-bash

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page