<!-- Auto-generated by scripts/skill_generator.py. Do not edit manually. -->
<!-- Regenerate with: just skills -->

# Namespace Module Methods

Extracted from source modules via introspection.

## S — State transforms

Compose with: `+` (union/merge) or `|` (pipe/chain)

| Method | Signature | Description |
|---|---|---|
| `S.accumulate()` | `(key: 'str', *, into: 'str | None' = None) -> 'STransform'` | Append ``state[key]`` to a running list at ``state[into]``. |
| `S.branch()` | `(key: 'str', **transforms: 'STransform') -> 'STransform'` | Route to different transforms based on a state key value. |
| `S.capture()` | `(key: 'str') -> 'STransform'` | Capture the most recent user message into state[key]. |
| `S.compute()` | `(**factories: 'Callable') -> 'STransform'` | Derive new keys from the full state dict. |
| `S.counter()` | `(key: 'str', step: 'int' = 1) -> 'STransform'` | Increment a numeric state value by *step* (default 1). |
| `S.default()` | `(**defaults: 'Any') -> 'STransform'` | Fill missing keys with default values. Existing keys are not overwritten. |
| `S.drop()` | `(*keys: 'str') -> 'STransform'` | Remove the specified keys from state. Only session-scoped keys are affected. |
| `S.flatten()` | `(key: 'str', separator: 'str' = '.') -> 'STransform'` | Flatten nested dict at ``state[key]`` into dotted keys. |
| `S.from_ui()` | `(*keys: 'str', surface: 'str' = 'default') -> 'STransform'` | Bridge A2UI data model values back into agent state. |
| `S.group_by()` | `(items_key: 'str', key_fn: 'Callable[[Any], Any]', into: 'str') -> 'STransform'` | Group list items by a key function. |
| `S.guard()` | `(predicate: 'Callable[[dict], bool]', msg: 'str' = 'State guard failed') -> 'STransform'` | Assert a state invariant. Raises ValueError if predicate is falsy. |
| `S.history()` | `(key: 'str', max_size: 'int' = 10) -> 'STransform'` | Keep a rolling window of past values at ``state[f"{key}_history"]``. |
| `S.identity()` | `() -> 'STransform'` | No-op transform. Passes state through unchanged. |
| `S.log()` | `(*keys: 'str', label: 'str' = '') -> 'STransform'` | Debug-print selected keys (or all state if no keys given). Returns no updates. |
| `S.merge()` | `(*keys: 'str', into: 'str', fn: 'Callable | None' = None) -> 'STransform'` | Combine multiple keys into one. Default join is newline concatenation. |
| `S.pick()` | `(*keys: 'str') -> 'STransform'` | Keep only the specified session-scoped keys. app:/user:/temp: keys are always pr |
| `S.rename()` | `(**mapping: 'str') -> 'STransform'` | Rename state keys. Unmapped session-scoped keys pass through unchanged. |
| `S.require()` | `(*keys: 'str') -> 'STransform'` | Assert that *keys* exist in state and are truthy. |
| `S.set()` | `(**values: 'Any') -> 'STransform'` | Set explicit key-value pairs in state (additive merge). |
| `S.to_ui()` | `(*keys: 'str', surface: 'str' = 'default') -> 'STransform'` | Bridge state keys into the A2UI data model. |
| `S.transform()` | `(key: 'str', fn: 'Callable') -> 'STransform'` | Apply a function to a single state value. |
| `S.unflatten()` | `(separator: 'str' = '.') -> 'STransform'` | Unflatten dotted keys back into nested dicts. |
| `S.validate()` | `(schema_cls: 'type', *, strict: 'bool' = False) -> 'STransform'` | Validate state against a Pydantic model or dataclass. |
| `S.when()` | `(predicate: 'Callable[[dict], bool] | str', transform: 'STransform') -> 'STransform'` | Conditional transform. Applies transform only if predicate(state) is truthy. |
| `S.zip()` | `(*keys: 'str', into: 'str' = 'zipped') -> 'STransform'` | Zip parallel lists into a list of tuples. |

## C — Context engineering

Compose with: `+` (union/merge) or `|` (pipe/chain)

| Method | Signature | Description |
|---|---|---|
| `C.budget()` | `(*, max_tokens: 'int' = 8000, overflow: 'str' = 'truncate_oldest') -> 'CBudget'` | Set token budget constraint for context. |
| `C.compact()` | `(*, strategy: 'str' = 'tool_calls') -> 'CCompact'` | Structural compaction — merge sequential same-author messages or tool calls. |
| `C.dedup()` | `(*, strategy: 'str' = 'exact', model: 'str' = 'gemini-2.5-flash') -> 'CDedup'` | Remove duplicate or redundant events. strategy='semantic' uses LLM. |
| `C.default()` | `() -> 'CTransform'` | Keep default conversation history (pass-through). |
| `C.distill()` | `(*, key: 'str' = 'facts', model: 'str' = 'gemini-2.5-flash') -> 'CDistill'` | Extract atomic facts from conversation via LLM. |
| `C.exclude_agents()` | `(*names: 'str') -> 'CExcludeAgents'` | Exclude outputs from named agents. |
| `C.extract()` | `(*, schema: 'dict | None' = None, key: 'str' = 'extracted', model: 'str' = 'gemini-2.5-flash') -> 'CExtract'` | Extract structured data from conversation via LLM. |
| `C.fit()` | `(*, max_tokens: 'int' = 4000, strategy: 'str' = 'strict', model: 'str' = 'gemini-2.5-flash') -> 'CFit'` | Aggressive pruning to fit a hard token limit. strategy='cascade' uses LLM. |
| `C.fresh()` | `(*, max_age: 'float' = 3600.0, stale_action: 'str' = 'drop') -> 'CFresh'` | Prune stale context based on event timestamp. |
| `C.from_agents()` | `(*names: 'str') -> 'CFromAgents'` | Include user messages + outputs from named agents. |
| `C.from_agents_windowed()` | `(**agent_windows: 'int') -> 'CFromAgentsWindowed'` | Per-agent selective windowing. |
| `C.from_state()` | `(*keys: 'str') -> 'CFromState'` | Read named keys from session state as context. |
| `C.last_n_turns()` | `(n: 'int') -> 'CWindow'` | Alias for C.window(n=n). |
| `C.manus_cascade()` | `(*, budget: 'int' = 8000, model: 'str' = 'gemini-2.5-flash') -> 'CManusCascade'` | Manus-inspired progressive compression cascade. |
| `C.none()` | `() -> 'CTransform'` | Suppress all conversation history. |
| `C.notes()` | `(key: 'str' = 'default', *, format: 'str' = 'plain') -> 'CNotes'` | Read structured notes from scratchpad at ``state["_notes_{key}"]``. |
| `C.priority()` | `(*, tier: 'int' = 2) -> 'CPriority'` | Set priority tier for context ordering. |
| `C.project()` | `(*fields: 'str') -> 'CProject'` | Keep only specified fields from event content. |
| `C.recent()` | `(*, decay: 'str' = 'exponential', half_life: 'int' = 10, min_weight: 'float' = 0.1) -> 'CRecent'` | Importance-weighted selection based on recency with exponential decay. |
| `C.redact()` | `(*patterns: 'str', replacement: 'str' = '[REDACTED]') -> 'CRedact'` | Remove PII or sensitive patterns from context via regex. |
| `C.relevant()` | `(*, query_key: 'str | None' = None, query: 'str | None' = None, top_k: 'int' = 5, model: 'str' = 'gemini-2.5-flash') -> 'CRelevant'` | Select events by semantic relevance to a query via LLM scoring. |
| `C.rolling()` | `(n: 'int' = 5, *, summarize: 'bool' = False, model: 'str' = 'gemini-2.5-flash') -> 'CRolling'` | Rolling window with optional summarization of older turns. |
| `C.select()` | `(*, author: 'str | tuple[str, ...] | None' = None, type: 'str | tuple[str, ...] | None' = None, tag: 'str | tuple[str, ...] | None' = None) -> 'CSelect'` | Filter events by metadata: author, type, and/or tag. |
| `C.summarize()` | `(*, scope: 'str' = 'all', model: 'str' = 'gemini-2.5-flash', prompt: 'str | None' = None, schema: 'dict | None' = None) -> 'CSummarize'` | Summarize context via LLM. Scope: 'all', 'before_window', 'tool_results'. |
| `C.template()` | `(text: 'str') -> 'CTemplate'` | Render a template string with {key} and {key?} state placeholders. |
| `C.truncate()` | `(*, max_turns: 'int | None' = None, max_tokens: 'int | None' = None, strategy: 'str' = 'tail') -> 'CTruncate'` | Hard limit on context by turn count or estimated tokens. |
| `C.user()` | `(*, strategy: 'str' = 'all') -> 'CUser'` | Select user messages with a strategy. |
| `C.user_only()` | `() -> 'CUserOnly'` | Include only user messages. |
| `C.validate()` | `(*checks: 'str', model: 'str' = 'gemini-2.5-flash') -> 'CValidate'` | Validate context quality. Checks: 'contradictions', 'completeness', 'freshness', |
| `C.when()` | `(predicate: 'Callable | str', block: 'CTransform') -> 'CWhen'` | Include block only if predicate is truthy at runtime. |
| `C.window()` | `(*, n: 'int' = 5) -> 'CWindow'` | Include last N turn-pairs from conversation history. |
| `C.with_ui()` | `(surface_id: 'str | None' = None) -> 'CTransform'` | Include current UI surface state in agent context. |
| `C.write_notes()` | `(key: 'str' = 'default', *, strategy: 'str' = 'append', source_key: 'str | None' = None) -> 'CWriteNotes'` | Write to scratchpad after agent execution. |

## P — Prompt composition

Compose with: `+` (union/merge) or `|` (pipe/chain)

| Method | Signature | Description |
|---|---|---|
| `P.adapt()` | `(*, audience: 'str' = 'general', model: 'str' = 'gemini-2.5-flash') -> 'PAdapt'` | Adapt the prompt's tone and complexity for a target audience. |
| `P.compress()` | `(*, max_tokens: 'int' = 500, model: 'str' = 'gemini-2.5-flash') -> 'PCompress'` | LLM-compress the prompt to reduce token count. |
| `P.constraint()` | `(*rules: 'str') -> 'PTransform'` | Add constraint(s). Multiple args create multiple constraint blocks that merge. |
| `P.context()` | `(text: 'str') -> 'PContext'` | Add background context the agent should know. |
| `P.example()` | `(text: 'str' = '', *, input: 'str' = '', output: 'str' = '') -> 'PExample'` | Add a few-shot example. |
| `P.format()` | `(text: 'str') -> 'PFormat'` | Specify the desired output format. |
| `P.from_state()` | `(*keys: 'str') -> 'PFromState'` | Read named keys from session state and format as context. |
| `P.only()` | `(*section_names: 'str') -> 'POnly'` | Keep only the named sections. Remove all others. |
| `P.reorder()` | `(*section_names: 'str') -> 'PReorder'` | Override default section ordering. Unmentioned sections appear after. |
| `P.role()` | `(text: 'str') -> 'PRole'` | Define the agent's role/persona. Rendered without a section header. |
| `P.scaffolded()` | `(block: 'PTransform', *, preamble: 'str' = 'You must follow these instructions carefully. Do not deviate from the specified task.', postamble: 'str' = 'Remember: stay on topic, be accurate, and follow all constraints above.') -> 'PScaffolded'` | Wrap a prompt in defensive scaffolding (safety preamble + postamble). |
| `P.section()` | `(name: 'str', text: 'str') -> 'PSection'` | Add a custom named section. |
| `P.task()` | `(text: 'str') -> 'PTask'` | Define the primary task or objective. |
| `P.template()` | `(text: 'str') -> 'PTemplate'` | Template with {key}, {key?}, and {ns:key} placeholders. |
| `P.ui_schema()` | `(*, catalog: 'str' = 'basic', examples: 'bool' = True) -> 'PSection'` | Inject A2UI schema and catalog documentation as a prompt section. |
| `P.versioned()` | `(block: 'PTransform', *, tag: 'str' = '') -> 'PVersioned'` | Attach version metadata + fingerprint to a prompt. |
| `P.when()` | `(predicate: 'Callable | str', block: 'PTransform') -> 'PWhen'` | Include block only if predicate is truthy at runtime. |
| `P.without()` | `(*section_names: 'str') -> 'PWithout'` | Remove the named sections. Keep all others. |

## A — Artifacts

Compose with: `+` (union/merge) or `|` (pipe/chain)

| Method | Signature | Description |
|---|---|---|
| `A.as_csv()` | `(key: 'str', *, columns: 'list[str] | None' = None) -> 'STransform'` | Parse CSV string in state[key] to list[dict]. |
| `A.as_json()` | `(key: 'str') -> 'STransform'` | Parse JSON string in state[key] to dict/list. |
| `A.as_text()` | `(key: 'str', *, encoding: 'str' = 'utf-8') -> 'STransform'` | Ensure state[key] is a decoded string. Decodes bytes if needed. |
| `A.delete()` | `(filename: 'str') -> 'ATransform'` | Delete all versions of an artifact. No state involvement. |
| `A.for_llm()` | `(filename: 'str', *, version: 'int | None' = None, scope: "Literal['session', 'user']" = 'session') -> 'CTransform'` | Load artifact directly into LLM context. No state bridge. |
| `A.from_csv()` | `(key: 'str') -> 'STransform'` | Serialize state[key] list[dict] to CSV string. |
| `A.from_json()` | `(key: 'str', *, indent: 'int | None' = None) -> 'STransform'` | Serialize state[key] dict/list to JSON string. |
| `A.from_markdown()` | `(key: 'str') -> 'STransform'` | Convert Markdown state[key] to HTML string. |
| `A.list()` | `(*, into_key: 'str') -> 'ATransform'` | List artifact filenames into state. Lightweight metadata only. |
| `A.load()` | `(filename: 'str', *, scope: "Literal['session', 'user']" = 'session') -> 'ATransform'` | Load artifact for pipeline composition. No state bridge. |
| `A.publish()` | `(filename: 'str', *, from_key: 'str', mime: 'str | None' = None, metadata: 'dict[str, Any] | None' = None, scope: "Literal['session', 'user']" = 'session') -> 'ATransform'` | Publish state content to artifact service. |
| `A.publish_many()` | `(*pairs: 'tuple[str, str]', mime: 'str | None' = None, scope: "Literal['session', 'user']" = 'session') -> 'tuple[ATransform, ...]'` | Batch publish: multiple (filename, from_key) pairs. |
| `A.save()` | `(filename: 'str', *, content: 'str | bytes', mime: 'str | None' = None, metadata: 'dict[str, Any] | None' = None, scope: "Literal['session', 'user']" = 'session') -> 'ATransform'` | Save literal content to artifact service. No state bridge. |
| `A.snapshot()` | `(filename: 'str', *, into_key: 'str', version: 'int | None' = None, decode: 'bool' = False, scope: "Literal['session', 'user']" = 'session') -> 'ATransform'` | Snapshot artifact content into state. |
| `A.snapshot_many()` | `(*pairs: 'tuple[str, str]', scope: "Literal['session', 'user']" = 'session') -> 'tuple[ATransform, ...]'` | Batch snapshot: multiple (filename, into_key) pairs. |
| `A.version()` | `(filename: 'str', *, into_key: 'str') -> 'ATransform'` | Get artifact version metadata into state. Lightweight metadata only. |
| `A.when()` | `(predicate: 'str | Callable', transform: 'ATransform') -> 'ATransform'` | Conditional artifact operation. Uniform with S.when(), C.when(), etc. |

## M — Middleware

Compose with: `+` (union/merge) or `|` (pipe/chain)

| Method | Signature | Description |
|---|---|---|
| `M.a2a_circuit_breaker()` | `(threshold: 'int' = 5, reset_after: 'float' = 60, *, agents: 'str | tuple[str, ...] | None' = None, on_open: 'Callable | None' = None, on_close: 'Callable | None' = None) -> 'MComposite'` | Circuit breaker for A2A remote agents. |
| `M.a2a_retry()` | `(max_attempts: 'int' = 3, backoff: 'float' = 2.0, *, agents: 'str | tuple[str, ...] | None' = None, on_retry: 'Callable | None' = None) -> 'MComposite'` | A2A-specific retry middleware for remote agent failures. |
| `M.a2a_timeout()` | `(seconds: 'float' = 30, *, agents: 'str | tuple[str, ...] | None' = None, on_timeout: 'Callable | None' = None) -> 'MComposite'` | Per-delegation timeout for A2A remote agent calls. |
| `M.a2ui_log()` | `(*, level: 'str' = 'info', agents: 'list[str] | None' = None) -> 'MComposite'` | Log A2UI surface operations (createSurface, updateComponents, etc.). |
| `M.after_agent()` | `(fn: 'Callable') -> 'MComposite'` | Single-hook middleware: fires after each agent. |
| `M.after_model()` | `(fn: 'Callable') -> 'MComposite'` | Single-hook middleware: fires after each LLM response. |
| `M.before_agent()` | `(fn: 'Callable') -> 'MComposite'` | Single-hook middleware: fires before each agent. |
| `M.before_model()` | `(fn: 'Callable') -> 'MComposite'` | Single-hook middleware: fires before each LLM request. |
| `M.cache()` | `(ttl: 'float' = 300, key_fn: 'Any' = None) -> 'MComposite'` | Cache LLM responses keyed by request content. |
| `M.circuit_breaker()` | `(threshold: 'int' = 5, reset_after: 'float' = 60) -> 'MComposite'` | Circuit breaker — trips open after N consecutive model errors. |
| `M.cost()` | `() -> 'MComposite'` | Token usage tracking middleware. |
| `M.dedup()` | `(window: 'int' = 10) -> 'MComposite'` | Suppress duplicate model calls within a sliding window. |
| `M.dispatch_log()` | `() -> 'MComposite'` | Dispatch/join lifecycle logging. |
| `M.fallback_model()` | `(model: 'str' = 'gemini-2.0-flash') -> 'MComposite'` | Auto-downgrade to fallback model on primary model failure. |
| `M.latency()` | `() -> 'MComposite'` | Per-agent latency tracking middleware. |
| `M.log()` | `() -> 'MComposite'` | Structured event logging middleware. |
| `M.metrics()` | `(collector: 'Any' = None) -> 'MComposite'` | Metrics collection (no-op if no collector provided). |
| `M.on_fallback()` | `(fn: 'Callable') -> 'MComposite'` | Single-hook middleware: fires at each fallback attempt. |
| `M.on_loop()` | `(fn: 'Callable') -> 'MComposite'` | Single-hook middleware: fires at each loop iteration. |
| `M.on_route()` | `(fn: 'Callable') -> 'MComposite'` | Single-hook middleware: fires when a route selects an agent. |
| `M.on_timeout()` | `(fn: 'Callable') -> 'MComposite'` | Single-hook middleware: fires when a timeout completes/expires. |
| `M.retry()` | `(max_attempts: 'int' = 3, backoff: 'float' = 1.0) -> 'MComposite'` | Retry middleware with exponential backoff. |
| `M.sample()` | `(rate: 'float', mw: 'MComposite | Any') -> 'MComposite'` | Probabilistic middleware — fires inner middleware only N% of the time. |
| `M.scope()` | `(agents: 'str | tuple[str, ...]', mw: 'MComposite | Any') -> 'MComposite'` | Restrict middleware to specific agents. |
| `M.timeout()` | `(seconds: 'float' = 30) -> 'MComposite'` | Per-agent execution timeout. |
| `M.topology_log()` | `() -> 'MComposite'` | Topology event logging (loops, fanout, routes, fallbacks, timeouts). |
| `M.trace()` | `(exporter: 'Any' = None) -> 'MComposite'` | OpenTelemetry span export (no-op if opentelemetry not installed). |
| `M.when()` | `(condition: 'str | Callable[[], bool] | type', mw: 'MComposite | Any') -> 'MComposite'` | Conditionally apply middleware. |

## T — Tool composition

Compose with: `+` (union/merge) or `|` (pipe/chain)

| Method | Signature | Description |
|---|---|---|
| `T.a2a()` | `(agent_card_url: 'str', *, name: 'str | None' = None, description: 'str | None' = None, timeout: 'float' = 600.0) -> 'TComposite'` | Wrap a remote A2A agent as an AgentTool. |
| `T.a2ui()` | `(*, catalog: 'str' = 'basic', schema: 'Any' = None) -> 'TComposite'` | A2UI toolset for LLM-guided UI generation. |
| `T.agent()` | `(agent_or_builder: 'Any') -> 'TComposite'` | Wrap an agent (or builder) as an AgentTool. |
| `T.cache()` | `(tool_or_composite: 'TComposite | Any', ttl: 'float' = 300, key_fn: 'Any' = None) -> 'TComposite'` | Wrap tool(s) with a TTL-based result cache. |
| `T.confirm()` | `(tool_or_composite: 'TComposite | Any', message: 'str | None' = None) -> 'TComposite'` | Wrap tool(s) with a confirmation requirement. |
| `T.fn()` | `(func_or_tool: 'Any', *, confirm: 'bool' = False) -> 'TComposite'` | Wrap a callable as a tool. |
| `T.google_search()` | `() -> 'TComposite'` | Google Search tool. |
| `T.mcp()` | `(url_or_params: 'Any', *, tool_filter: 'Any' = None, prefix: 'str | None' = None) -> 'TComposite'` | Thin factory over :class:`McpToolset` builder. |
| `T.mock()` | `(name: 'str', *, returns: 'Any' = None, side_effect: 'Any' = None) -> 'TComposite'` | Create a mock tool that returns a fixed value or side-effect. |
| `T.openapi()` | `(spec: 'Any', *, tool_filter: 'Any' = None, auth: 'Any' = None) -> 'TComposite'` | Thin factory over :class:`OpenAPIToolset` builder. |
| `T.schema()` | `(schema_cls: 'type') -> 'TComposite'` | Attach a ToolSchema for contract checking. |
| `T.search()` | `(registry: 'Any', *, always_loaded: 'list[str] | None' = None, max_tools: 'int' = 20) -> 'TComposite'` | BM25-indexed dynamic tool loading (two-phase pattern). |
| `T.timeout()` | `(tool_or_composite: 'TComposite | Any', seconds: 'float' = 30) -> 'TComposite'` | Wrap tool(s) with a per-invocation timeout. |
| `T.toolset()` | `(ts: 'Any') -> 'TComposite'` | Wrap any ADK toolset (MCPToolset, etc.). |
| `T.transform()` | `(tool_or_composite: 'TComposite | Any', *, pre: 'Any' = None, post: 'Any' = None) -> 'TComposite'` | Wrap tool(s) with pre/post argument/result transforms. |

## E — Evaluation

Compose with: `+` (union/merge) or `|` (pipe/chain)

| Method | Signature | Description |
|---|---|---|
| `E.case()` | `(prompt: 'str', *, expect: 'str | None' = None, tools: 'list[tuple[str, dict[str, Any]]] | None' = None, rubrics: 'list[str] | None' = None, state: 'dict[str, Any] | None' = None) -> 'ECase'` | Create a standalone eval case. |
| `E.compare()` | `(*agents: 'Any') -> 'ComparisonSuite'` | Compare multiple agents on the same eval set. |
| `E.custom()` | `(name: 'str', fn: 'Callable[..., float]', *, threshold: 'float' = 0.5) -> 'EComposite'` | User-defined custom metric. |
| `E.from_dir()` | `(path: 'str') -> 'list[Any]'` | Load all eval sets from a directory. |
| `E.from_file()` | `(path: 'str') -> 'Any'` | Load an eval set from a JSON file. |
| `E.gate()` | `(criteria: 'EComposite', *, threshold: 'float | None' = None, output_key: 'str | None' = None) -> 'Any'` | Create a quality gate for use in pipelines. |
| `E.hallucination()` | `(threshold: 'float' = 0.8, *, judge_model: 'str' = 'gemini-2.5-flash', check_intermediate: 'bool' = False) -> 'EComposite'` | Hallucination detection criterion. |
| `E.persona()` | `()` | Namespace for prebuilt user simulation personas. |
| `E.response_match()` | `(threshold: 'float' = 0.8) -> 'EComposite'` | ROUGE-1 response match criterion. |
| `E.rubric()` | `(*texts: 'str', threshold: 'float' = 0.5, judge_model: 'str' = 'gemini-2.5-flash') -> 'EComposite'` | Rubric-based response quality criterion. |
| `E.safety()` | `(threshold: 'float' = 1.0) -> 'EComposite'` | Safety evaluation criterion. |
| `E.scenario()` | `(start: 'str', plan: 'str', *, persona: 'Any | None' = None) -> 'Any'` | Create a conversation scenario for user simulation. |
| `E.semantic_match()` | `(threshold: 'float' = 0.5, *, judge_model: 'str' = 'gemini-2.5-flash') -> 'EComposite'` | LLM-as-a-judge semantic matching criterion. |
| `E.suite()` | `(agent: 'Any') -> 'EvalSuite'` | Create an evaluation suite for an agent builder. |
| `E.tool_rubric()` | `(*texts: 'str', threshold: 'float' = 0.5, judge_model: 'str' = 'gemini-2.5-flash') -> 'EComposite'` | Rubric-based tool use quality criterion. |
| `E.trajectory()` | `(threshold: 'float' = 1.0, *, match: 'str' = 'exact') -> 'EComposite'` | Tool trajectory matching criterion. |

## G — Guards

Compose with: `+` (union/merge) or `|` (pipe/chain)

| Method | Signature | Description |
|---|---|---|
| `G.a2ui()` | `(*, max_components: 'int' = 50, allowed_types: 'list[str] | None' = None, deny_types: 'list[str] | None' = None) -> 'GComposite'` | Validate LLM-generated A2UI output. |
| `G.budget()` | `(max_tokens: 'int') -> 'GComposite'` | Enforce a token budget. |
| `G.custom()` | `(fn: 'Callable[..., Any]') -> '_CustomDetector'` | Wrap an async callable as a PII detector. |
| `G.custom_judge()` | `(fn: 'Callable[..., Any]') -> '_CustomJudge'` | Wrap an async callable as a content judge. |
| `G.dlp()` | `(project: 'str', *, info_types: 'list[str] | None' = None, location: 'str' = 'global') -> '_DLPDetector'` | Create a Google Cloud DLP-based PII detector. |
| `G.grounded()` | `(sources_key: 'str' = 'sources') -> 'GComposite'` | Require model output to be grounded in source material. |
| `G.hallucination()` | `(threshold: 'float' = 0.7, *, sources_key: 'str' = 'sources', judge: 'ContentJudge | None' = None) -> 'GComposite'` | Detect hallucinated content not supported by sources. |
| `G.input()` | `(schema_cls: 'type') -> 'GComposite'` | Validate model input against a schema class. |
| `G.json()` | `() -> 'GComposite'` | Validate that model output is valid JSON. |
| `G.length()` | `(*, min: 'int' = 0, max: 'int' = 100000) -> 'GComposite'` | Enforce output length bounds. |
| `G.llm_judge()` | `(model: 'str' = 'gemini-2.5-flash') -> '_LLMJudge'` | Create a placeholder LLM-based content judge. |
| `G.max_turns()` | `(n: 'int') -> 'GComposite'` | Enforce maximum conversation turns. |
| `G.multi()` | `(*detectors: 'Any') -> '_MultiDetector'` | Combine multiple PII detectors, deduplicating by span. |
| `G.output()` | `(schema_cls: 'type') -> 'GComposite'` | Validate model output against a schema class. |
| `G.pii()` | `(action: 'str' = 'redact', *, detector: 'PIIDetector | None' = None, threshold: 'float' = 0.5, replacement: 'str' = '[PII]') -> 'GComposite'` | Detect and handle PII in model output. |
| `G.rate_limit()` | `(rpm: 'int') -> 'GComposite'` | Enforce requests-per-minute limit. |
| `G.regex()` | `(pattern: 'str', *, action: 'str' = 'block', replacement: 'str' = '[REDACTED]') -> 'GComposite'` | Block or redact text matching a regex pattern. |
| `G.regex_detector()` | `(patterns: 'list[str] | dict[str, str] | None' = None) -> '_RegexDetector'` | Create a regex-based PII detector. |
| `G.topic()` | `(deny: 'list[str]') -> 'GComposite'` | Block output that discusses denied topics. |
| `G.toxicity()` | `(threshold: 'float' = 0.8, *, judge: 'ContentJudge | None' = None) -> 'GComposite'` | Block toxic model output. |
| `G.when()` | `(predicate: 'Callable[[Any], bool]', guard: 'GComposite | GGuard') -> 'GComposite'` | Conditionally apply a guard based on a state predicate. |
