research-agent
A bounded research agent: loop … until, budgets, monitors, and tool calling.
Run it from sema/:
sema check examples/research-agentSEMA_STRICT=1 sema run examples/research-agentsema assure examples/research-agent --grade silverSource
Section titled “Source”src/main.sema
Section titled “src/main.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 neurosymboliccomponents composing in real Sema app code — all imported from `std.*`, compiledand 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, rewritefrom std.belief import Belieffrom std.document import Report, renderfrom 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
Section titled “Reflected API”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() -> None !{model.invoke, model.embed, observe.record}Returns None
Effects !{model.invoke, model.embed, observe.record}