foley.agent.tools#

The SELECT orchestration: find() / plan() + the small pure tool wrappers.

This is the one seam that serves the Python API, the agent loop, and the future MCP server (#12) — the same functions, three surfaces (report 05 §5.2). It OWNS every side-effecting call (search → gate → verify → decide → generate → place); decide() is a pure tail step that only branches.

find() opens one foley.obs.run('find') scope, so the nested foley.search() / foley.generate() façade calls aggregate into a single reproducible run-manifest (report 10 §1.3); each stage emits a typed Step and each LLM rung a GenAI span. The plan it emits is the sparse SoundDesignTimeline subset — WEAVE (#8) resolves anchors, mix, and mastering.

import foley stays dol-only: foley.search / foley.generate and the generation-error hierarchy are imported lazily inside the functions that call them.

Functions

estimate_find_usd(*[, max_events, backend, ...])

An upper bound on what one find() run can spend, or None if unknown.

find(context, *[, max_events, seconds, ...])

The headline: a narrative context → verified, license-clean sound candidates.

generate_sound(query, *[, backend, library])

Generate a clip for query (the fallback tool) — a thin wrapper over foley.generate.

place_in_timeline(clip, *[, onset, gain, ...])

Emit the SPARSE per-item plan subset (clip_ref·onset·gain·layer·loop) — no more.

plan(candidates, *[, transcript])

Fold verified candidates into the SPARSE SoundDesignTimeline (the SELECT→WEAVE bridge).

search_sounds(queries, *[, k, library, filters])

Hybrid search for one query, or a multi-query RRF-merge (the SELECT retrieval tool).

foley.agent.tools.estimate_find_usd(*, max_events=6, backend='auto', llm=None, k=10, verify='listen', max_refine_loops=1, max_generations=1, injected=None, context_chars=0)[source]#

An upper bound on what one find() run can spend, or None if unknown.

Every generation (max_generations per event through backend) plus every LLM call the default rungs could make: one decomposition, max_refine_loops refinements per event, k judge calls per retrieval pass above the clap rung, and one re-verification per generation. Injected rungs are the caller’s to meter (their real calls are still checked one by one).

Return type:

Optional[float]

foley.agent.tools.find(context, *, max_events=6, seconds=None, intended_use=None, backend='auto', verify='listen', stream=False, k=10, tau_retrieve=0.5, tau_clap=0.35, max_refine_loops=1, budget=None, library=None, decomposer=None, judge=None, refiner=None, llm=None)[source]#

The headline: a narrative context → verified, license-clean sound candidates.

decompose → (per event) refine/search → verify_match ladder → decide (with the fail-closed license gate FIRST) → place (report 05 §5). Works out of the box — foley.find("She pushed open the heavy oak door; rain hammered outside.") — with deterministic defaults; every model / threshold / seam is an optional keyword.

Parameters:
  • context (str) – The narrative passage.

  • max_events (int) – The sparse density cap on decomposed events.

  • seconds (Optional[float]) – Optional passage duration (density-window hint; forwarded).

  • intended_use (Optional[IntendedUse]) – The caller’s rights intent (default: foley.licensing.DEFAULT_INTENDED_USE — commercial publishing; NC / SA material is refused unless you pass a different intent).

  • backend (str) – Generation backend for the fallback ('auto' → foley.generate’s default).

  • verify (Union[str, VerifyLevel]) – The max verify rung — 'clap' | 'listen' | 'judge'.

  • stream (bool) – If True, return a generator yielding one Candidate per resolved event; else return the collected list.

  • k (int) – Retrieval shortlist depth per query.

  • tau_retrieve (float) – Confidence threshold to auto-accept a retrieved clip.

  • tau_clap (float) – The clap-rung gate threshold.

  • max_refine_loops (int) – Max refine→re-retrieve passes per event (also the default Budget).

  • budget (Optional[Budget]) – An explicit Budget (overrides max_refine_loops). It is also the run’s spend cap: Budget(max_usd=...) (default $1; $3 when llm='anthropic' or $FOLEY_LLM=anthropic, whose default run is bounded at about $2.52 — foley.cost.DEFAULT_MAX_USD_BY_LLM) bounds every paid call the run makes — generations and paid LLM rungs — cumulatively, and a call of unknown cost needs Budget(approve_unknown_cost=True) (#57).

  • library – Target SoundLibrary (default: the process-wide default).

  • refiner (decomposer / judge /) – Injected DI seams (Decomposer / Judge / Refiner); each defaults to the llm provider’s implementation.

  • llm (Optional[str]) – Which LLM the decompose / refine / judge rungs use when not injected — 'fake' | 'local' | 'anthropic'. None reads $FOLEY_LLM, then falls back to the free default (a configured local endpoint, else the deterministic fake). A key being present never opts in to paid calls.

Return type:

Union[list[Candidate], Iterator[Candidate]]

Returns:

list[Candidate] (stream=False) or an Iterator[Candidate] (stream=True) — one verified, license-clean candidate per resolved event.

foley.agent.tools.generate_sound(query, *, backend='auto', library=None)[source]#

Generate a clip for query (the fallback tool) — a thin wrapper over foley.generate.

Returns a Candidate (origin=generated); raises the GenerationError hierarchy on refusal / no-result (caught fail-closed by _generate_and_reverify()).

Return type:

Candidate

foley.agent.tools.place_in_timeline(clip, *, onset=None, gain=0.0, layer=Layer.sfx_fg, loop=False)[source]#

Emit the SPARSE per-item plan subset (clip_ref·onset·gain·layer·loop) — no more.

onset stays a SYMBOLIC anchor string (never a resolved offset); mix / processing / alignment / mastering are WEAVE’s (#8) job, not SELECT’s.

Return type:

TimelineItem

foley.agent.tools.plan(candidates, *, transcript=None)[source]#

Fold verified candidates into the SPARSE SoundDesignTimeline (the SELECT→WEAVE bridge).

One TimelineItem per candidate (onset·gain·layer·loop only, from its SoundEvent), joined to the run-artifact via run_manifest_ref — the reserved #8 plan_ref slot is filled when called inside an active foley.obs run scope (None-safe otherwise).

Parameters:
  • candidates (list[Candidate]) – The candidates returned by find().

  • transcript (Optional[str]) – Optional narration transcript (WEAVE resolves the reference).

Return type:

SoundDesignTimeline

foley.agent.tools.search_sounds(queries, *, k=10, library=None, filters=None)[source]#

Hybrid search for one query, or a multi-query RRF-merge (the SELECT retrieval tool).

Delegates a single query VERBATIM to SoundLibrary.search() (so the retrieval ranking the nDCG@10 gate measures is untouched); a multi-query list runs each query and RRF-merges (k=RRF_K) — the query-expansion recall lever, exercised only on a refine pass.

Parameters:
  • queries (Union[str, list[str]]) – One query string, or a list of paraphrases to merge.

  • k (int) – Number of results.

  • library – Target library (default: the process-wide default).

  • filters (Optional[dict]) – Extra SoundLibrary.search() kwargs (e.g. the license prefilter).

Return type:

list[Candidate]