Define the acceptance contract
Public Preview

Request Web research with source links

Requesting Web research with source-linked claims lets your application reject incomplete results before a person reviews the sources.

Define a dated public question, retain claim-linked sources and evidence gaps in the response model, and review material sources before accepting results.

  • The acceptance contract specifies the public question, validity date, source types, and conflict reporting rules.
  • The response model requires source material per claim but does not prove claim truth.
  • SOURCE_REVIEW_REQUIRED is not an approval signal; open material sources and apply the full acceptance test.
  • If response.model() raises an error, record response.task_id and check task state before submitting a replacement.

Summaries were generated by AI. Generative AI is experimental.

Use this guide after you can submit a typed task with the Python SDK. Request dated claims, final source URLs, disagreements, and evidence gaps. Your application can reject an incomplete result before a person reviews the sources.

Define the acceptance contract

Before you submit the task, define:

  • the public question and the date at which the answer must be valid;
  • the material claims that need support and the preferred primary source types;
  • how the result must report conflicts, missing dates, and evidence gaps;
  • the claims that need a person or an independent rule-based check.

The coordinating agent delegates a bounded brief to the Web research executor; it does not copy the full task history. Keep that brief public. Context isolation does not redact a credential, private URL, confidential passage, or unnecessary personal data that the coordinating agent includes in the brief.

Request source-linked fields

The following example is illustrative. It uses a placeholder topic and is not a tested, runnable example.

import asyncio
from datetime import UTC, datetime, timedelta
from pydantic import BaseModel, Field

from duale import ask, create_sdk


class Evidence(BaseModel):
    final_url: str
    publisher: str
    published_at: str | None = None
    excerpt: str


class Claim(BaseModel):
    text: str
    sources: list[Evidence] = Field(min_length=1)


class WebResearchResult(BaseModel):
    answer: str
    claims: list[Claim] = Field(default_factory=list)
    disagreements: list[str] = Field(default_factory=list)
    evidence_gaps: list[str] = Field(default_factory=list)
    valid_as_of: str


async def main() -> None:
    async with create_sdk() as sdk:
        response = await ask(
            action=(
                "Research this public topic: <public, non-sensitive topic>. "
                "Give an answer valid as of <YYYY-MM-DD>. Prefer primary sources. "
                "For each material claim, return the final URL, publisher, publication date, "
                "and a short supporting excerpt from every source you use. Report disagreements "
                "and evidence gaps. Return no claim when the available pages do not support it."
            ),
            res=WebResearchResult,
            deadline=datetime.now(UTC) + timedelta(minutes=10),
            sdk=sdk,
        )
        result = await response.model()

        if not result.claims:
            print(response.task_id, "STOP: no supported claims")
            return

        print(
            response.task_id,
            "SOURCE_REVIEW_REQUIRED",
            len(result.claims),
            len(result.evidence_gaps),
        )


asyncio.run(main())

When the result contains at least one source-linked claim, the example prints:

<task_id> SOURCE_REVIEW_REQUIRED <claim_count> <gap_count>

Choose a deadline that fits your workflow. The ten-minute deadline above is an example, not a web completion guarantee.

The response model gives the final task result a fixed shape and requires source material for each returned claim. It does not expose the internal Web research record or prove that a publisher is independent or a claim is true.

Review the sources

SOURCE_REVIEW_REQUIRED is not an approval signal. Open the material sources and apply the full acceptance test in Sources and factuality. If a source fails, narrow the claim, request another public source, or keep an evidence gap.

Recover safely

If response.model() raises an SDK or validation error, record response.task_id and read Errors and reliability before you submit another task. A submission with a new task identifier creates new work.

Before you submit a replacement task, check the first task’s state and any external effect from your registered tools. Secure integration explains repeat-safe tool design and approval.

If the result contains no supported claim, keep the gap. Change one search condition at a time or use another public source.