Websearch Plugin Model

Smarter API WebsearchPlugin Manifest Constants.

Note

Experimental. The WebsearchPlugin was designed and coded by Claude Code (Anthropic’s Claude Opus 5.5), with Lawrence McDaniel as co-author. It is experimental, and will be documented.

smarter.apps.plugin.manifest.models.websearch_plugin.const.MAX_DOMAINS = 100

The maximum number of domains in an allow list or a block list.

smarter.apps.plugin.manifest.models.websearch_plugin.const.MAX_FETCH_CHARACTERS = 100000

The maximum number of characters of a web page that a plugin can return.

smarter.apps.plugin.manifest.models.websearch_plugin.const.MAX_QUERY_LENGTH = 400

The maximum length of a search query, in characters.

smarter.apps.plugin.manifest.models.websearch_plugin.const.MAX_RESULTS = 20

The maximum number of search results that a plugin can return.

smarter.apps.plugin.manifest.models.websearch_plugin.const.MAX_URL_LENGTH = 2048

The maximum length of a URL to fetch, in characters.

Enumeration classes for the WebsearchPlugin manifest models.

Note

Experimental. The WebsearchPlugin was designed and coded by Claude Code (Anthropic’s Claude Opus 5.5), with Lawrence McDaniel as co-author. It is experimental, and will be documented.

class smarter.apps.plugin.manifest.models.websearch_plugin.enum.WebsearchFreshness(*values)[source]

Bases: SmarterEnumAbstract

Restricts search results to those published within a period.

DAY = 'day'
MONTH = 'month'
WEEK = 'week'
YEAR = 'year'
class smarter.apps.plugin.manifest.models.websearch_plugin.enum.WebsearchOperation(*values)[source]

Bases: SmarterEnumAbstract

The operations that a WebsearchPlugin’s tool performs.

FETCH = 'fetch'
SEARCH = 'search'
class smarter.apps.plugin.manifest.models.websearch_plugin.enum.WebsearchProvider(*values)[source]

Bases: SmarterEnumAbstract

The web search APIs that a WebsearchPlugin can use.

BRAVE = 'brave'

Brave Search API.

https://brave.com/search/api/

TAVILY = 'tavily'

Tavily Search API, which is designed for LLMs.

https://tavily.com

class smarter.apps.plugin.manifest.models.websearch_plugin.enum.WebsearchSafeSearch(*values)[source]

Bases: SmarterEnumAbstract

Filtering of adult content from search results.

MODERATE = 'moderate'
OFF = 'off'
STRICT = 'strict'

Domain policy for the WebsearchPlugin: which websites it may search and read.

A WebsearchPlugin manifest may restrict the plugin to an allow list of domains, e.g. a company’s own documentation, and may exclude a block list of domains. The LLM may narrow this policy further, per tool call, but can never widen it.

A domain matches itself and all of its subdomains. For example, python.org matches python.org and docs.python.org, but not notpython.org.

policy = DomainPolicy.create(allowed=["python.org"], blocked=["wiki.python.org"])
policy.permits_url("https://docs.python.org/3/")  # True
policy.permits_url("https://wiki.python.org/moin/")  # False: blocked
policy.permits_url("https://example.com/")  # False: not allowed

Note

Experimental. The WebsearchPlugin was designed and coded by Claude Code (Anthropic’s Claude Opus 5.5), with Lawrence McDaniel as co-author. It is experimental, and will be documented.

class smarter.apps.plugin.manifest.models.websearch_plugin.policy.DomainPolicy(allowed=(), blocked=())[source]

Bases: object

The domains that a WebsearchPlugin may search and read.

Variables:
  • allowed – If not empty, only these domains, and their subdomains, are permitted.

  • blocked – These domains, and their subdomains, are never permitted. The block list takes precedence over the allow list.

__init__(allowed=(), blocked=())
allowed: tuple[str, ...] = ()
blocked: tuple[str, ...] = ()
classmethod create(allowed=None, blocked=None)[source]

Create a policy from lists of domain names, which are normalized.

Return type:

DomainPolicy

describe()[source]

Describe the policy in a sentence, for the LLM, or return an empty string if it is unrestricted.

Return type:

str

narrow(allowed=None, blocked=None)[source]

Return a policy that is at least as restrictive as this one.

This is how the LLM restricts an individual tool call, e.g. to search only one website. Requested allowed domains must lie within this policy’s allowed domains, if it has any. Requested blocked domains are added to this policy’s blocked domains.

Parameters:
Return type:

DomainPolicy

Returns:

The narrowed policy.

Raises:

WebsearchPolicyError – If a requested allowed domain is outside this policy’s allowed domains, or is blocked by it.

permits_host(host)[source]

Return True if the policy permits a host.

Return type:

bool

permits_url(url)[source]

Return True if the policy permits the host of a URL.

Return type:

bool

exception smarter.apps.plugin.manifest.models.websearch_plugin.policy.WebsearchPolicyError(message='')[source]

Bases: SmarterValueError

Raised when a domain is invalid, or a request would widen a plugin’s domain policy.

smarter.apps.plugin.manifest.models.websearch_plugin.policy.host_matches(host, domain)[source]

Return True if a host is the domain, or one of its subdomains.

Return type:

bool

smarter.apps.plugin.manifest.models.websearch_plugin.policy.normalize_domain(domain)[source]

Normalize a domain name.

Leading wildcards (*.) and dots, and trailing dots, are removed, since a domain always matches its subdomains. Internationalized domain names are converted to their ASCII (punycode) form.

Parameters:

domain (str) – A domain name, e.g. *.Example.COM.

Return type:

str

Returns:

The normalized domain name, e.g. example.com.

Raises:

WebsearchPolicyError – If the value is not a domain name, e.g. a URL or an IP address with a port.

smarter.apps.plugin.manifest.models.websearch_plugin.policy.normalize_domains(domains)[source]

Normalize a list of domain names, removing duplicates while preserving order.

Raises:

WebsearchPolicyError – If a domain is invalid, or there are too many.

Return type:

tuple[str, ...]

smarter.apps.plugin.manifest.models.websearch_plugin.policy.url_host(url)[source]

Return the lower case host of a URL, or None if it has none.

Return type:

str | None

Smarter API Manifest - WebsearchPlugin.spec.

A WebsearchPlugin gives the LLM access to the open web, through one tool that performs two operations, like the web search and web fetch tools of Claude itself:

  • search the web for a query, via a web search API, and return ranked results, each with a title, URL and snippet, for the LLM to cite.

  • fetch a web page by URL, and return its main content as Markdown.

spec.websearchData configures each operation. Include a search section to enable search, and a fetch section to enable fetch. At least one is required.

websearchData:
  search:
    provider: brave            # brave or tavily
    apiKey: brave_search_key   # the name of a Smarter Secret containing the api key
    maxResults: 5
    safeSearch: moderate
    country: us
    language: en
    freshness: null            # day, week, month or year
  fetch:
    maxCharacters: 20000
    respectRobotsTxt: true
  allowedDomains: []           # if not empty, only these domains may be searched and read
  blockedDomains: []           # these domains are never searched nor read
  timeout: 15
  cacheTtl: 3600

Note

Experimental. The WebsearchPlugin was designed and coded by Claude Code (Anthropic’s Claude Opus 5.5), with Lawrence McDaniel as co-author. It is experimental, and will be documented.

class smarter.apps.plugin.manifest.models.websearch_plugin.spec.SAMWebsearchPluginSpec(*, selector: SAMPluginCommonSpecSelector, prompt: SAMPluginCommonSpecPrompt, websearchData: WebsearchData)[source]

Bases: SAMPluginCommonSpec

Smarter API Manifest - WebsearchPlugin.spec.

class_identifier: ClassVar[str] = 'WebsearchPlugin.spec'
model_config = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

websearchData: WebsearchData
class smarter.apps.plugin.manifest.models.websearch_plugin.spec.WebsearchData(*, search: WebsearchSearch | None = None, fetch: WebsearchFetch | None = None, allowedDomains: list[str] | None = None, blockedDomains: list[str] | None = None, timeout: Annotated[int, Ge(ge=1), Le(le=60)] = 15, cacheTtl: Annotated[int, Ge(ge=0), Le(le=86400)] = PluginCacheTtl.WEBSEARCH)[source]

Bases: SmarterBasePydanticModel

Smarter API - WebsearchPlugin.spec.websearchData.

allowedDomains: list[str] | None
blockedDomains: list[str] | None
cacheTtl: int
class_identifier: ClassVar[str] = 'WebsearchPlugin.spec'
property domain_policy: DomainPolicy

The domain policy.

fetch: WebsearchFetch | None
model_config = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

search: WebsearchSearch | None
timeout: int
classmethod validate_domains(v)[source]

Validate and normalize domain names.

Return type:

list[str] | None

validate_websearch_data()[source]

Validate that at least one operation is enabled.

Return type:

WebsearchData

class smarter.apps.plugin.manifest.models.websearch_plugin.spec.WebsearchFetch(*, maxCharacters: Annotated[int, Ge(ge=1000), Le(le=100000)] = 20000, respectRobotsTxt: bool = True)[source]

Bases: SmarterBasePydanticModel

Smarter API - WebsearchPlugin.spec.websearchData.fetch: reading web pages by URL.

class_identifier: ClassVar[str] = 'WebsearchPlugin.spec.fetch'
maxCharacters: int
model_config = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

respectRobotsTxt: bool
class smarter.apps.plugin.manifest.models.websearch_plugin.spec.WebsearchSearch(*, provider: Literal['brave', 'tavily'], apiKey: str, maxResults: Annotated[int, Ge(ge=1), Le(le=20)] = 5, safeSearch: Literal['off', 'moderate', 'strict'] = 'moderate', country: str | None = None, language: str | None = None, freshness: Literal['day', 'week', 'month', 'year'] | None = None)[source]

Bases: SmarterBasePydanticModel

Smarter API - WebsearchPlugin.spec.websearchData.search: web search, via a web search API.

apiKey: str
class_identifier: ClassVar[str] = 'WebsearchPlugin.spec.search'
country: str | None
freshness: Literal['day', 'week', 'month', 'year'] | None
language: str | None
maxResults: int
model_config = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

provider: Literal['brave', 'tavily']
safeSearch: Literal['off', 'moderate', 'strict']
classmethod validate_api_key(v)[source]

Validate that the api key is the name of a Secret, not empty.

Return type:

str

classmethod validate_country(v)[source]

Validate the country code.

Return type:

str | None

classmethod validate_freshness(v)[source]

Validate the default freshness.

Return type:

str | None

classmethod validate_language(v)[source]

Validate the language code.

Return type:

str | None

classmethod validate_provider(v)[source]

Validate the provider.

Return type:

str

Validate the safe search level.

Return type:

str

Smarter API Manifest - WebsearchPlugin.

Note

Experimental. The WebsearchPlugin was designed and coded by Claude Code (Anthropic’s Claude Opus 5.5), with Lawrence McDaniel as co-author. It is experimental, and will be documented.

class smarter.apps.plugin.manifest.models.websearch_plugin.model.SAMWebsearchPlugin(*, apiVersion: str, kind: str, metadata: SAMPluginCommonMetadata, spec: SAMWebsearchPluginSpec, status: SAMPluginCommonStatus | None = None)[source]

Bases: SAMPluginCommon

Smarter API Manifest - WebsearchPlugin Model.

class_identifier: ClassVar[str] = 'WebsearchPlugin'
model_config = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

spec: SAMWebsearchPluginSpec