Skip to content
Closed
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,45 @@ All notable changes to the You.com Python SDK will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.5.0] - 2026-09-21

Minor release. Adds support for the new `knowledge` parameter on
`POST /v1/search` and the knowledge result models that come back with it.
Purely additive — no breaking changes.

### Added

- **`knowledge` parameter on `search()` and `search_async()`** — pass
`knowledge="core"` to request knowledge results backed by licensed data
providers such as encyclopedias, market-data firms, and reference publishers.
They arrive in their own section at `response.results.knowledge`. `"core"` is
the only value the API accepts, and anything else raises `ValidationError`
locally rather than reaching the network, mirroring the server's `422`.
- **`Knowledge` enum** — `Knowledge.CORE`, exported from `youdotcom.models`.
Plain strings are accepted and normalized, so `knowledge="core"` and
`knowledge="CORE"` both work.
- **`KnowledgeResult` and `KnowledgeAttribution` models** — a knowledge result
carries `type`, `title`, and `attribution`, plus `description` and an optional
`as_of` date for `type: answer` results, the only kind returned today. `type`
is modeled as a plain `str` so an unrecognized kind parses instead of raising,
since a new kind may populate a different set of fields. Attribution entries
are credits rather than citations and carry no URL.
- **`Results.knowledge`** — new optional field on the search response container.
Up to 25 results are returned, limited to those relevant to the query. When
none are relevant the API omits the key entirely, so the field is `None`
rather than an empty list and iterating needs an `or []` guard. `count` caps
the web and news sections, not knowledge.

### Changed

- **`scripts/check_drift.py` recurses nested response schemas** — the response
check previously compared top-level fields only, so drift inside a nested
object went undetected. Two pre-existing gaps that recursion surfaced
(`AnswerSearchResult.description` / `.thumbnail_url` and
`FinanceResearchSource.snippets`) are listed in an explicit
`KNOWN_RESPONSE_GAPS` table that reports itself stale once the SDK catches up,
rather than being silently ignored.

## [3.4.0] - 2026-09-08

Minor release. The `metadata` format on the Contents API is now deprecated
Expand Down
36 changes: 34 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,38 @@ available and crawls the page live otherwise, `"cache"` returns cached
content only (`contents` is omitted for results with none), and `"fetch"`
always crawls the page live.

#### Knowledge results

Pass `knowledge="core"` to add cards backed by licensed data providers —
encyclopedias, market-data firms, reference publishers. They come back in
their own section:

```python
import os
from youdotcom import You

with You(api_key_auth=os.getenv("YDC_API_KEY"), timeout_ms=60_000) as you:
res = you.search(
query="what is the capital of France",
knowledge="core",
)
for card in res.results.knowledge or []:
print(card.title)
print(card.description)
print([credit.name for credit in card.attribution])
```

`"core"` is the only value the API accepts; anything else raises
`ValidationError` locally, mirroring the server's `422`. Results are limited
to those relevant to the query, up to 25, and when none are relevant the API
omits the section entirely — so `results.knowledge` is `None` rather than an
empty list. Iterate with `or []`.

`count` caps the web and news sections, not knowledge. Attribution entries
are credits rather than citations: each names a provider and carries no URL.
`as_of`, when present, is the `YYYY-MM-DD` date the card's underlying data
covers.

### Contents

Clean HTML or Markdown for a list of URLs.
Expand Down Expand Up @@ -346,8 +378,8 @@ retries = RetryConfig(
retry_connection_errors=True,
)

with You(api_key_auth=key, retry_config=retries) as you: # whole client
res = you.search(query="...", retries=retries) # or one call
with You(api_key_auth=key, retry_config=retries, timeout_ms=60_000) as you: # whole client
res = you.search(query="...", retries=retries) # or one call
```

Retries apply to `429`, `500`, `502`, `503`, and `504`.
Expand Down
40 changes: 40 additions & 0 deletions USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,46 @@ Unknown keys inside `extraction` raise `ValidationError` locally, and passing
`ValueError` — both mirror the server's 422 contract so callers fail-fast.
<!-- End SDK Example Usage [extraction] -->

<!-- Start SDK Example Usage [knowledge] -->
```python
# Add knowledge cards backed by licensed data providers.
import os
from youdotcom import You


with You(
api_key_auth=os.getenv("YDC_API_KEY"),
timeout_ms=60_000,
) as you:

res = you.search(
query="what is the capital of France",
knowledge="core",
)

for card in res.results.knowledge or []:
print(card.title, card.description)
print([credit.name for credit in card.attribution])
```

`knowledge="core"` requests knowledge results — cards backed by licensed data
providers such as encyclopedias, market-data firms, and reference publishers.
`"core"` is the only value the API accepts; anything else raises
`ValidationError` locally, mirroring the server's 422.

Results are limited to those relevant to the query, up to 25. When none are
relevant the API omits the section, so `results.knowledge` is `None` rather
than an empty list — iterate with `or []`. `count` caps the web and news
sections, not knowledge.

Each card carries `type`, `title`, and `attribution`; for `type: answer` — the
only kind returned today — `description` is present and `as_of` is an optional
`YYYY-MM-DD` date covering the card's underlying data. `type` is a plain
string so an unrecognized kind parses rather than raises; ignore a value you
do not recognize. Attribution entries are credits rather than citations: each
names a provider and carries no URL.
<!-- End SDK Example Usage [knowledge] -->

<!-- Start SDK Example Usage [attribution] -->
```python
# Tag every outbound request with a caller-identity header so the
Expand Down
4 changes: 2 additions & 2 deletions docs/models/contentsrequest.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

| Field | Type | Required | Description | Example |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `urls` | List[*str*] | :heavy_minus_sign: | Array of URLs to fetch the contents from. | |
| `formats` | List[[models.ContentsFormats](../models/contentsformats.md)] | :heavy_minus_sign: | Array of content formats to return. All included formats are returned in the response. The "metadata" format is deprecated and will be removed in a future major release. | [<br/>"html",<br/>"markdown"<br/>] |
| `urls` | Optional[List[*str*]] | :heavy_minus_sign: | Array of URLs to fetch the contents from. | |
| `formats` | Optional[List[[models.ContentsFormats](../models/contentsformats.md)]] | :heavy_minus_sign: | Array of content formats to return. All included formats are returned in the response. The "metadata" format is deprecated and will be removed in a future major release. | [<br/>"html",<br/>"markdown"<br/>] |
| `crawl_timeout` | *Optional[int]* | :heavy_minus_sign: | Maximum time in seconds to wait for page content. Must be between 1 and 60 seconds. Default is 10 seconds. | 10 |
| `max_age` | *OptionalNullable[int]* | :heavy_minus_sign: | Maximum allowed age of cached content in seconds. When set, cached content older than this threshold is ignored and the page is re-fetched. Must be 0 or greater. Default: null (no age limit, cached content is returned regardless of age). | 86400 |
2 changes: 1 addition & 1 deletion docs/models/financeresearchdetail.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
| `loc` | List[[models.FinanceResearchLoc](../models/financeresearchloc.md)] | :heavy_check_mark: | The location of the error as a path of segments (strings for field names, integers for byte offsets). | [<br/>"body",<br/>"input"<br/>] |
| `msg` | *str* | :heavy_check_mark: | A human-readable description of the error. | Field required |
| `input` | [models.FinanceResearchInputUnion](../models/financeresearchinputunion.md) | :heavy_check_mark: | The input value that caused the error. | |
| `ctx` | Dict[str, *Any*] | :heavy_minus_sign: | Additional context about the error. | |
| `ctx` | Optional[Dict[str, *Any*]] | :heavy_minus_sign: | Additional context about the error. | |
24 changes: 24 additions & 0 deletions docs/models/knowledge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Knowledge

Requests knowledge results alongside web and news search.

## Example Usage

```python
from youdotcom.models import Knowledge

value = Knowledge.CORE
```


## Values

| Name | Value |
| ------ | ----- |
| `CORE` | core |

## Notes

`core` is the only value the API accepts. Passing anything else raises
`ValidationError` locally rather than reaching the network, mirroring the
server's `422`.
Loading
Loading