# Adding Builders

This guide explains how to customize builder generation by editing the manual seed file and regenerating.

## How Builder Customization Works

The codegen pipeline merges two seed sources:

1. **`seeds/seed.toml`** -- auto-generated by `seed_generator.py` from `manifest.json`. This file is overwritten on every `just seed` run.
1. **`seeds/seed.manual.toml`** -- hand-curated overrides. This file is **never overwritten** and takes priority during the merge.

To customize builders, edit `seeds/seed.manual.toml`.

## Renaming Builders

The `[renames]` section maps ADK class names to friendlier builder names:

```toml
[renames]
LlmAgent = "Agent"
SequentialAgent = "Pipeline"
ParallelAgent = "FanOut"
LoopAgent = "Loop"
```

This means `from adk_fluent import Agent` creates a builder for `LlmAgent`.

## Optional Constructor Arguments

Add optional positional parameters to a builder's `__init__`:

```toml
[builders.Agent]
optional_constructor_args = ["model"]
```

This enables `Agent("name", "model")` as a shorthand for `Agent("name").model("model")`.

## Adding Extras (Non-Field Methods)

Extras are methods that do not map directly to an ADK field. They are defined as `[[builders.X.extras]]` entries:

```toml
[[builders.Agent.extras]]
name = "guardrail"
signature = "(self, fn: Callable) -> Self"
doc = "Attach a guardrail function as both before_model and after_model callback."
behavior = "dual_callback"
target_fields = ["before_model_callback", "after_model_callback"]
```

Each extra has:

| Key             | Description                                          |
| --------------- | ---------------------------------------------------- |
| `name`          | Method name on the builder                           |
| `signature`     | Python signature string                              |
| `doc`           | Docstring for the method                             |
| `behavior`      | Code generation behavior (see below)                 |
| `target_fields` | ADK fields this extra writes to (behavior-dependent) |
| `helper_func`   | Helper function to call (for runtime behaviors)      |

### Behavior Types

- **`dual_callback`** -- registers the function on two callback fields (e.g., guardrail -> before_model + after_model)
- **`runtime_helper`** -- calls a synchronous helper function (e.g., `.ask()`)
- **`runtime_helper_async`** -- calls an async helper function (e.g., `.ask_async()`)
- **`runtime_helper_async_gen`** -- returns an async generator (e.g., `.stream()`, `.events()`)
- **`runtime_helper_ctx`** -- returns a context manager (e.g., `.session()`)

### Example: Adding a Runtime Helper

```toml
[[builders.Agent.extras]]
name = "ask"
signature = "(self, prompt: str) -> str"
doc = "One-shot execution. Build agent, send prompt, return response text."
behavior = "runtime_helper"
helper_func = "run_one_shot"
```

This generates a `.ask()` method that calls the `run_one_shot` helper function with the built agent and prompt.

## Regenerating After Changes

After editing `seeds/seed.manual.toml`, regenerate everything:

```bash
just all
```

This runs the full pipeline: scan -> seed (with merge) -> generate -> docs.

To verify the changes:

```bash
just test       # Run all tests
just typecheck  # Check type stubs
```

## Adding a Completely New Builder

If you need to add a builder for an ADK class that is not automatically discovered by the scanner:

1. Add a `[builders.MyClass]` section to `seeds/seed.manual.toml`
1. Define the class name, module path, and any extras
1. Run `just all` to regenerate

However, in most cases the scanner automatically discovers all relevant ADK classes. Manual builder definitions are primarily for adding extras and customizations to auto-discovered builders.
