% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/workflow__research_enumeration.R
\name{asa_enumerate}
\alias{asa_enumerate}
\title{Multi-Agent Research for Open-Ended Queries}
\usage{
asa_enumerate(
  query = NULL,
  schema = NULL,
  output = c("data.frame", "csv", "json"),
  config = NULL,
  workers = NULL,
  max_rounds = NULL,
  budget = list(queries = 50L, tokens = 200000L, time_sec = 300L),
  stop_policy = list(target_items = NULL, plateau_rounds = 2L, novelty_min = 0.05,
    novelty_window = 20L),
  sources = list(web = TRUE, wikipedia = TRUE, wikidata = TRUE),
  allow_read_webpages = NULL,
  webpage_relevance_mode = NULL,
  webpage_embedding_provider = NULL,
  webpage_embedding_model = NULL,
  temporal = NULL,
  pagination = TRUE,
  progress = TRUE,
  include_provenance = FALSE,
  checkpoint = TRUE,
  checkpoint_dir = tempdir(),
  resume_from = NULL,
  agent = NULL,
  backend = NULL,
  model = NULL,
  conda_env = NULL,
  verbose = TRUE
)
}
\arguments{
\item{query}{Character string describing the research goal. Required for fresh
runs; optional when \code{resume_from} points to an existing checkpoint.
Examples: "Find all current US senators with their state, party, and term end date"}

\item{schema}{Named character vector defining the output schema.
Names are column names, values are R types ("character", "numeric", "logical").
Use NULL or "auto" for LLM-proposed schema.}

\item{output}{Output format: "data.frame" (default), "csv", or "json".}

\item{config}{Optional \code{asa_config} object to supply defaults for agent
initialization and per-run search/temporal settings. Explicit arguments to
\code{asa_enumerate()} take precedence over \code{config}.}

\item{workers}{Number of parallel search workers. Defaults to value from
\code{config$workers} when provided, otherwise \code{ASA_DEFAULT_WORKERS}
(typically 4).}

\item{max_rounds}{Maximum research iterations. Defaults to value from
\code{ASA_DEFAULT_MAX_ROUNDS} (typically 8).}

\item{budget}{Named list with resource limits:
\itemize{
  \item queries: Maximum search queries (default: 50)
  \item tokens: Maximum LLM tokens (default: 200000)
  \item time_sec: Maximum execution time in seconds (default: 300)
}}

\item{stop_policy}{Named list with stopping criteria:
\itemize{
  \item target_items: Stop when this many items found (NULL = unknown)
  \item plateau_rounds: Stop after N rounds with no new items (default: 2)
  \item novelty_min: Minimum new items ratio per round (default: 0.05)
  \item novelty_window: Window size for novelty calculation (default: 20)
}}

\item{sources}{Named list controlling which sources to use:
\itemize{
  \item web: Use DuckDuckGo web search (default: TRUE)
  \item wikipedia: Use Wikipedia (default: TRUE)
  \item wikidata: Use Wikidata SPARQL for authoritative enumerations (default: TRUE)
}}

\item{allow_read_webpages}{If TRUE, the agent may open and read full webpages
(in addition to search snippets) when it helps extraction. Use NULL
(default) to inherit from \code{config$search} (when provided); otherwise
defaults to FALSE for safety and to avoid large context usage.}

\item{webpage_relevance_mode}{Relevance selection for opened webpages.
One of: "auto" (default), "lexical", "embeddings". When "embeddings" or
"auto" with an available provider, the tool uses vector similarity to pick
the most relevant excerpts; otherwise it falls back to lexical overlap.}

\item{webpage_embedding_provider}{Embedding provider to use for relevance.
One of: "auto" (default), "openai", "sentence_transformers".}

\item{webpage_embedding_model}{Embedding model identifier. For OpenAI,
defaults to "text-embedding-3-small". For sentence-transformers, use a
local model name (e.g., "all-MiniLM-L6-v2").}

\item{temporal}{Named list for temporal filtering:
\itemize{
  \item after: ISO 8601 date string (e.g., "2020-01-01") - results after this date
  \item before: ISO 8601 date string (e.g., "2024-01-01") - results before this date
  \item time_filter: DuckDuckGo time filter ("d", "w", "m", "y") for day/week/month/year
  \item strictness: "best_effort" (default) or "strict" (verifies dates via metadata)
  \item use_wayback: Use Wayback Machine for strict pre-date guarantees (default: FALSE)
}}

\item{pagination}{Enable pagination for large result sets (default: TRUE).}

\item{progress}{Show progress bar and status updates (default: TRUE).}

\item{include_provenance}{Include source URLs and confidence per row (default: FALSE).}

\item{checkpoint}{Enable auto-save after planning and each completed round
(default: TRUE).}

\item{checkpoint_dir}{Directory for checkpoint files (default: tempdir()).}

\item{resume_from}{Path to checkpoint file to resume from (default: NULL).
For v2 checkpoints this continues execution from the last saved round
state. Legacy v1 checkpoints return the saved result without continuation.}

\item{agent}{An initialized \code{asa_agent} object. If NULL, uses the current
agent or creates a new one with specified backend/model.}

\item{backend}{LLM backend if creating new agent: "openai", "groq", "xai",
"gemini", "exo", "ollama", "openrouter", "anthropic", or "bedrock".}

\item{model}{Model identifier if creating new agent.}

\item{conda_env}{Conda environment name. Defaults to the package option
\code{asa.default_conda_env} (or \code{"asa_env"} if unset).}

\item{verbose}{Print status messages (default: TRUE).}
}
\value{
An object of class \code{asa_enumerate_result} containing:
  \itemize{
    \item data: data.frame with results matching the schema
    \item status: "complete", "partial", or "failed"
    \item stop_reason: Why the search stopped
    \item metrics: List with rounds, queries_used, novelty_curve, coverage
    \item provenance: If include_provenance=TRUE, source info per row
    \item checkpoint_file: Path to checkpoint if saved
  }
}
\description{
Performs intelligent open-ended research tasks using multi-agent orchestration.
Decomposes complex queries into sub-tasks, executes parallel searches, and
aggregates results into structured output (data.frame, CSV, or JSON).
}
\details{
The function uses an iterative graph architecture:
\enumerate{
  \item \strong{Planner}: Decomposes the query and proposes a search plan.
  \item \strong{Searcher}: Queries Wikidata (when applicable) and falls back to web/Wikipedia.
  \item \strong{Deduper}: Removes duplicates using hashing + fuzzy matching.
  \item \strong{Stopper}: Evaluates stopping criteria (novelty, budgets, saturation).
}

Parallelism is limited and backend-dependent. For example, strict temporal
filtering may verify publication dates in parallel up to \code{workers}.

For known entity types (US senators, countries, Fortune 500), Wikidata provides
authoritative enumerations with complete, verified data.
}
\section{Checkpointing}{

With checkpoint=TRUE, state is saved after planning and after each completed
round. If interrupted, use resume_from to continue from the last checkpoint:
\preformatted{
result <- asa_enumerate(resume_from = "/path/to/checkpoint.rds")
}
}

\section{Schema}{

The schema defines expected output columns:
\preformatted{
schema = c(name = "character", state = "character", party = "character")
}
With schema = "auto", the planner agent proposes a schema based on the query.
}

\examples{
\dontrun{
# Find all US senators
senators <- asa_enumerate(
  query = "Find all current US senators with state, party, and term end date",
  schema = c(name = "character", state = "character",
             party = "character", term_end = "character"),
  stop_policy = list(target_items = 100),
  include_provenance = TRUE
)
head(senators$data)

# Find countries with auto schema
countries <- asa_enumerate(
  query = "Find all countries with their capitals and populations",
  schema = "auto",
  output = "csv"
)

# Resume from checkpoint
result <- asa_enumerate(
  query = "Find Fortune 500 CEOs",
  resume_from = "/tmp/asa_enumerate_abc123.rds"
)

# Temporal filtering: results from specific date range
companies_2020s <- asa_enumerate(
  query = "Find tech companies founded recently",
  temporal = list(
    after = "2020-01-01",
    before = "2024-01-01",
    strictness = "best_effort"
  )
)

# Temporal filtering: past year with DuckDuckGo time filter
recent_news <- asa_enumerate(
  query = "Find AI research breakthroughs",
  temporal = list(
    time_filter = "y"  # past year
  )
)

# Strict temporal filtering with Wayback Machine
historical <- asa_enumerate(
  query = "Find Fortune 500 companies",
  temporal = list(
    before = "2015-01-01",
    strictness = "strict",
    use_wayback = TRUE
  )
)
}

}
\seealso{
\code{\link{run_task}}, \code{\link{initialize_agent}}
}
