Library API

Updated Jul 27, 2026

Podbot can be embedded as a Rust library dependency in addition to its use as a CLI tool. The podbot::api module exposes orchestration functions that accept library-owned types and return typed outcomes without printing to stdout/stderr or calling std::process::exit.

The supported stable embedding boundary is:

  • podbot::api
  • podbot::config
  • podbot::error

The cli module is optional behind the cli feature. Hidden compatibility modules such as engine and GitHub integration shims are not part of the supported semver contract for embedders.

Available API items

Item Description
podbot::api::exec(config, request) Execute in a container
podbot::api::ExecContext::connect(…) Reuse runtime and engine state
podbot::api::RunRequest::new(repo, branch) Build the library-owned run request
podbot::api::RepositoryRef Validate repository owner/name
podbot::api::BranchName Validate a branch value
podbot::api::WorkspacePath Validate a workspace path

Table: Podbot API functions for executing and connecting to containers.

Return type

The stable execution entry points podbot::api::exec(config, request) and podbot::api::ExecContext::exec(request) return podbot::error::Result<CommandOutcome>:

  • CommandOutcome::Success indicates a zero exit code.
  • CommandOutcome::CommandExit { code } carries the non-zero exit code reported by the container engine.

podbot::api::ExecContext::connect(…) returns podbot::error::Result<ExecContext>, which embedders can cache and reuse for repeated exec calls.

For repeated exec calls, embedders can cache engine state:

use podbot::api::{ExecContext, ExecRequest};
use podbot::config::AppConfig;

fn run_many_commands(runtime: &tokio::runtime::Handle) -> Result<(), podbot::error::PodbotError> {
    let config = AppConfig::default();
    let context = ExecContext::connect(&config, runtime)?;
    let request = ExecRequest::new("my-container", vec![String::from("echo")])?;
    let _ = context.exec(&request)?;
    Ok(())
}

Example usage

use podbot::api::{CommandOutcome, ExecMode, ExecRequest, exec};
use podbot::config::AppConfig;

fn run_command() -> Result<(), podbot::error::PodbotError> {
    let config = AppConfig::default();
    let request = ExecRequest::new(
        "my-container",
        vec![String::from("echo"), String::from("hello")],
    )?
    .with_mode(ExecMode::Attached)
    .with_tty(false);

    match exec(&config, &request)? {
        CommandOutcome::Success => println!("Command succeeded"),
        CommandOutcome::CommandExit { code } => {
            println!("Command exited with code {code}");
        }
    }

    Ok(())
}

Git identity configuration

configure_container_git_identity remains available as a compatibility helper, but it is not part of the stable embedding contract described here because its parameters and results depend on internal engine-owned traits and types. Library embedders should treat it as an internal shim rather than a semver stable API.

Repository cloning

clone_repository_into_workspace is available via the internal Cargo feature and is not part of the stable embedding contract. Stable embedders interact with repository cloning exclusively through the validated value types: RepositoryRef::parse, BranchName::parse, and WorkspacePath::parse. Validation failures surface as ConfigError; clone or branch verification failures surface as ContainerError::ExecFailed.

Library embedding

Podbot can be used as a library dependency without the CLI adapter layer. The cli Cargo feature controls the visibility of the podbot::cli module, which contains Clap parse types. This feature is enabled by default.

To depend on Podbot as a library without the CLI types:

[dependencies]
podbot = { version = "0.1.0", default-features = false }

With this configuration, the podbot::cli module is not compiled, and the consumer can use the library without interacting with Clap types directly.

Note: The clap crate remains a transitive dependency through ortho_config at present, so it is still pulled into the dependency tree. The feature flag controls module visibility, not the clap dependency itself.

Stable modules

The following modules are part of the stable public API:

  • podbot::api — orchestration types and exec entry points (exec, ExecContext, ExecRequest, ExecMode, RunRequest, CommandOutcome)
  • podbot::config — configuration types and loaders (AppConfig, ConfigLoadOptions, load_config)
  • podbot::error — semantic error hierarchy (PodbotError, ConfigError, ContainerError)

Internal modules

The following modules are only exported when the crate is built with feature = "internal" or for podbot's own crate tests. They are not available to normal embedders and are not part of the supported semver contract:

  • podbot::engine — container engine types and traits
  • podbot::github — GitHub App authentication types

Adapter modules

The following modules are public but gated behind Cargo features:

  • podbot::cli — Clap parse types (requires the cli feature, enabled by default)

Experimental API

The following functions remain available under podbot::api, but they are not part of the stable semver contract described in this guide. Podbot reserves the experimental Cargo feature for unstable library surfaces, and these stub entry points are available only when that feature is enabled.

  • podbot::api::run_agent(config, request) — validates GitHub credentials and returns a stub success outcome for a RunRequest.
  • podbot::api::stop_container(container) — placeholder stop operation that currently returns a stub success outcome.
  • podbot::api::list_containers() — placeholder list operation that currently returns a stub success outcome.
  • podbot::api::run_token_daemon(container_id) — placeholder token-refresh daemon entry point that currently returns a stub success outcome.

Enable the experimental entry points with this dependency declaration:

[dependencies]
podbot = { version = "0.1.0", features = ["experimental"] }

`run_agent`

Experimental: This function is not part of the stable API contract. Enable feature = "experimental" before importing this function.

use podbot::api::{RunRequest, run_agent};
use podbot::config::AppConfig;

fn start_agent() -> Result<(), podbot::error::PodbotError> {
    let config = AppConfig::default();
    let request = RunRequest::new("owner/name", "main")?;
    run_agent(&config, &request)?;
    Ok(())
}

run_agent(config: &AppConfig, request: &RunRequest) validates the GitHub credential fields in AppConfig and accepts the repository and branch through the library-owned request type. If any GitHub credential field is set, all required fields (app_id, installation_id, private_key_path) must be present; the function returns a PodbotError if validation fails. Call this function when you want to embed the full agent orchestration path rather than issuing individual exec commands.

Note: The agent runtime is currently a stub; the function validates credentials and returns CommandOutcome::Success without launching a persistent agent loop.

`run_token_daemon`

Experimental: This function is not part of the stable API contract. Enable feature = "experimental" before importing this function.

use podbot::api::run_token_daemon;

fn start_token_refresh(container_id: &str) -> Result<(), podbot::error::PodbotError> {
    run_token_daemon(container_id)?;
    Ok(())
}

run_token_daemon(container_id: &str) starts the token-refresh daemon for the named container. Supply the container identifier or name as returned by the container engine. The daemon periodically refreshes authentication tokens required by the agent.

Note: The token daemon is currently a stub and returns CommandOutcome::Success immediately.