sac — Search as Code: agentic search orchestration using LLMs.
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 withsearch,llm,fs,utilsattributesSaCAgent— Multi-turn research agent that generates and executes search codeSearchSDK— Web search via Exa MCP (free) or Brave Search APILLMSDKClient— LLM integration via OpenAI-compatible APIFilesystemSDK— Persistent key-value storeUtilsSDK— Deduplication, filtering, flattening, coverage summarizationSandbox— 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>
Metadata
Release files for sac-agent 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sac_agent-0.1.0.tar.gz | 20.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sac_agent-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 45.9 kB
Release files / sac_agent-0.1.0.tar.gz
| Download URL | sac_agent-0.1.0.tar.gz |
|---|---|
| Size | 20.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c43b5a7504d9e05052ccfe9112814f17839066f26f07fabe5172d0b3e357a26a
|
|
BLAKE2b-256 checksum How to use checksums |
36306adff1b8906d079704ace0323fa691ce0f198911b5385b5ca77b0eb60d77
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 3, 2026.
Transparency logRelease files / sac_agent-0.1.0-py3-none-any.whl
| Download URL | sac_agent-0.1.0-py3-none-any.whl |
|---|---|
| Size | 25.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1d8cf1bff7a7eb323f18e6fca0891eebda75d524560a6af690a4bf0f9165f45e
|
|
BLAKE2b-256 checksum How to use checksums |
b6cb5ed237636f5fb574c373f3e3d9c78e3fb7798f6cd2f4f86eaf9974d4b740
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 3, 2026.
Transparency log