<!-- Sema documentation — research-agent
     Sema is a new AI-native, neurosymbolic programming language most models
     have not been trained on. Full corpus: https://sema.49.12.246.95.sslip.io/llms-full.txt
     Install language support: https://sema.49.12.246.95.sslip.io/install-skill/ -->

# research-agent

> A bounded research agent: loop … until, budgets, monitors, and tool calling.

> A bounded research agent: loop … until, budgets, monitors, and tool calling.

Run it from `sema/`:

```bash
sema check examples/research-agent
SEMA_STRICT=1 sema run examples/research-agent
sema assure examples/research-agent --grade silver
```

## Source

### `src/main.sema`

```sema
"""research-agent — a small end-to-end pipeline built on the Sema standard library.

A compact replica of a search→write research flow, showing the neurosymbolic
components composing in real Sema app code — all imported from `std.*`, compiled
and run:

  • provenance   — assign global citation ids + rewrite markers (std.provenance)
  • semantic     — de-duplicate candidate facts (semantic.dedup verb)
  • agent loop   — iterate until a belief crosses threshold (std.agent_loop + std.belief)
  • metering     — track model spend ambiently (`with meter`)
  • document     — render a typed report to markdown (std.document)

Run:  sema run examples/research-agent
"""

from std.provenance import Cit, Doc, build_url_to_id, rewrite
from std.belief import Belief
from std.document import Report, render
from std.collections import join_str

def main() -> None !{model.invoke, model.embed, observe.record}:
    # 1. Sources with local citations → stable global ids + rewritten text.
    docs = [
        Doc(text="Solar capacity grew [1]. Costs fell [2].",
            citations=[Cit(url="iea.org", start=20, end=23), Cit(url="irena.org", start=36, end=39)]),
        Doc(text="Costs fell sharply [1].",
            citations=[Cit(url="irena.org", start=19, end=22)]),
    ]
    ids = build_url_to_id(docs)
    mut sections: list[str] = []
    for d in docs:
        sections.append(rewrite(d.text, d.citations, ids))

    # 2. Candidate facts, de-duplicated semantically.
    unique_facts = semantic.dedup(["costs fell", "costs fell", "capacity grew"], 0.99)

    # 3. Belief-driven loop: iterate until confidence crosses the threshold,
    #    bounded by the evidence available — the `loop … until` surface syntax.
    decisions = [0.7, 0.85, 0.95]
    mut belief = Belief(alpha=1.0, beta=1.0, history=[0.5])
    mut iters = 0
    loop until belief.confidence() >= 0.7 max_iters len(decisions):
        belief.update(decisions[iters])
        iters = iters + 1

    # 4. Draft a synthesis with ambient usage metering — no usage tuples.
    mut calls = 0
    mut cost = 0.0
    with meter as u:
        _synthesis = generate("Summarize renewable energy findings", 64)
        calls = u.total_calls
        cost = u.cost

    # 5. Render a typed report to markdown.
    r = Report(
        title="Renewable Energy Findings",
        context="Auto-synthesized from " + str(len(docs)) + " sources.",
        confidence=belief.confidence(),
        rationale="Confidence is a Beta-Bernoulli posterior over iteration evidence.",
        takeaways=unique_facts,
        section_titles=["Findings"],
        sections_text=join_str(sections, "\n\n"),
        conclusion="Costs continue to decline as capacity scales.",
    )
    print(render(r, "\n"))
    log.info("run", stopped_iter=iters, confidence=belief.confidence(), model_calls=calls, cost=cost)
```

## Reflected API

# `main`

research-agent — a small end-to-end pipeline built on the Sema standard library.

A compact replica of a search→write research flow, showing the neurosymbolic
components composing in real Sema app code — all imported from `std.*`, compiled
and run:

  • provenance   — assign global citation ids + rewrite markers (std.provenance)
  • semantic     — de-duplicate candidate facts (semantic.dedup verb)
  • agent loop   — iterate until a belief crosses threshold (std.agent_loop + std.belief)
  • metering     — track model spend ambiently (`with meter`)
  • document     — render a typed report to markdown (std.document)

Run:  sema run examples/research-agent

# `def main`

```sema
def main() -> None !{model.invoke, model.embed, observe.record}
```

**Returns** `None`

**Effects** `!{model.invoke, model.embed, observe.record}`
