Skip to main content

Search as Code (SaC) — agentic search orchestration using LLMs

Project description

sac — Search as Code: agentic search orchestration using LLMs.

PyPI Python Ruff DeepWiki

Install

pip install sac
uv pip install sac-agent

Usage

from sac import AgenticSearchSDK, SaCAgent

sdk = AgenticSearchSDK()
agent = SaCAgent(task="Research the latest AI papers on retrieval-augmented generation", sdk=sdk)
answer = agent.run()
print(answer)

CLI

sac "What are the latest developments in LLM agents?"
sac -v "Verbose research mode"
sac --endpoint https://opencode.ai/zen/v1 --model big-pickle "task"
sac --final-report ./report.md "task"
sac --final-report-format json --final-report ./output "task"
sac  # interactive mode

API

  • AgenticSearchSDK — Composable SDK with search, llm, fs, utils attributes
  • SaCAgent — Multi-turn research agent that generates and executes search code
  • SearchSDK — Web search via Exa MCP (free) or Brave Search API
  • LLMSDKClient — LLM integration via OpenAI-compatible API
  • FilesystemSDK — Persistent key-value store
  • UtilsSDK — Deduplication, filtering, flattening, coverage summarization
  • Sandbox — Executes generated Python code in a restricted namespace

Code Library

Every code snippet the agent generates can be saved as a reusable, callable function with --with-code-library:

sac --with-code-library "Research the latest AI papers"

Functions are grouped by concern into ~/.cache/sac-agent/library/ (classification priority: extraction > synthesis > search > storage > analysis > pipeline):

File Concern
extraction.py sdk.llm.extract_many operations
synthesis.py sdk.llm.synthesize operations
search.py sdk.search.* operations
storage.py sdk.fs.* operations
analysis.py sdk.utils.* operations
pipeline.py Mixed / catch-all

Execution flow:

CLI (sac "task")
  → SaCAgent.run()
    → _call_model()                   # LLM generates JSON with "code"
    → sandbox.execute(code)           # exec() in restricted namespace
    → if successful: library.collect()  # save snippet in memory
    → repeat up to 6 turns
    → on synthesis: library.flush_all()
      → _classify_code() per snippet  # extraction > synthesis > search > ...
      → append to category file       # search.py / extraction.py / pipeline.py

Each function accepts sdk as its first parameter and has a Google-style docstring:

def search_fanout(sdk, queries, limit_per_query=5, concurrency=3):
    """Execute parallel searches across multiple queries and flatten results.

    Args:
        sdk: AgenticSearchSDK instance
        queries: List of search query strings
        limit_per_query: Results per query (default: 5)
        concurrency: Number of parallel workers (default: 3)

    Returns:
        Flattened list of SearchResult objects
    """
    results = sdk.search.web_many(queries, ...)
    return sdk.utils.flatten(results)

Load functions by name at runtime:

from sac.library import load_function

fn = load_function("search_fanout_1234")
results = fn(sdk)

Development

git clone https://github.com/daedalus/SAC.git
cd SAC
pip install -e ".[test]"

# run tests
pytest

# format
ruff format src/ tests/

# format markdown
mdformat .

# lint + type check (prospector runs ruff check + mypy + pylint together)
prospector --with-tool ruff --with-tool mypy --with-tool pylint src/

# find unused code (vulture reports dead code with 90%+ confidence)
vulture --min-confidence 90 src/

# analyze code complexity (lizard reports cyclomatic complexity, NLOC, etc.)
lizard src/ --CCN=15

## References

This project is inspired by and implements the architecture described in:

> Perplexity AI. "Rethinking Search as Code Generation." *Perplexity Research*, June 1, 2026.
> <https://research.perplexity.ai/articles/rethinking-search-as-code-generation>

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

sac_agent-0.1.0.tar.gz (20.4 kB view details)

Uploaded Source

Built Distribution

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

sac_agent-0.1.0-py3-none-any.whl (25.5 kB view details)

Uploaded Python 3

File details

Details for the file sac_agent-0.1.0.tar.gz.

File metadata

  • Download URL: sac_agent-0.1.0.tar.gz
  • Upload date:
  • Size: 20.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sac_agent-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c43b5a7504d9e05052ccfe9112814f17839066f26f07fabe5172d0b3e357a26a
MD5 f1c4445ca9f536ed1267e67079e6a4fc
BLAKE2b-256 36306adff1b8906d079704ace0323fa691ce0f198911b5385b5ca77b0eb60d77

See more details on using hashes here.

Provenance

The following attestation bundles were made for sac_agent-0.1.0.tar.gz:

Publisher: pypi-publish.yml on daedalus/sac-agent

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

File details

Details for the file sac_agent-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: sac_agent-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sac_agent-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1d8cf1bff7a7eb323f18e6fca0891eebda75d524560a6af690a4bf0f9165f45e
MD5 c9aea54d260120b6beb039fd8d761b67
BLAKE2b-256 b6cb5ed237636f5fb574c373f3e3d9c78e3fb7798f6cd2f4f86eaf9974d4b740

See more details on using hashes here.

Provenance

The following attestation bundles were made for sac_agent-0.1.0-py3-none-any.whl:

Publisher: pypi-publish.yml on daedalus/sac-agent

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