> ## Documentation Index
> Fetch the complete documentation index at: https://agno-v2-codex-docs-audit-20260719-0149.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Data extraction

> Extract typed Pydantic objects from text, images, audio, video, and PDFs.

Define the schema, pass the input, get a validated object back.

<Tip>
  Use a fast, low-cost model like `gemini-3.5-flash` for high-volume extraction.
</Tip>

```python theme={null}
from typing import Optional

from agno.agent import Agent
from agno.models.google import Gemini
from pydantic import BaseModel, Field


class Contact(BaseModel):
    name: Optional[str] = Field(None, description="Full name as written")
    email: Optional[str] = Field(None, description="Email address")
    phone: Optional[str] = Field(None, description="Phone number, raw format")
    company: Optional[str] = Field(None, description="Company or organization")
    title: Optional[str] = Field(None, description="Job title")


agent = Agent(
    model=Gemini(id="gemini-3.5-flash"),
    instructions=(
        "Extract contact information from the input. Use exactly what the "
        "text shows. If a field is missing, leave it null. Do not guess."
    ),
    output_schema=Contact,
)

result = agent.run(
    "Hi - Sarah Johnson, VP of Marketing at Acme Corp. "
    "sarah@acme.com / +1-555-0102."
).content
# Contact(name='Sarah Johnson', email='sarah@acme.com',
#         phone='+1-555-0102', company='Acme Corp.', title='VP of Marketing')
```

The hard part is getting missing fields back as `null` instead of a hallucinated value. Spell it out in the instructions: "If a field is missing, leave it null. Do not guess."

## Nested objects

Lists of sub-objects work the same way. Define the inner model and reference it.

```python theme={null}
from typing import List, Optional

from pydantic import BaseModel, Field


class ActionItem(BaseModel):
    owner: str = Field(..., description="Person responsible")
    description: str = Field(..., description="What needs to be done")
    due_date: Optional[str] = Field(None, description="Due date if stated")


class Meeting(BaseModel):
    action_items: List[ActionItem] = Field(default_factory=list)
```

Pass `output_schema=Meeting` and the agent returns a `Meeting` with a populated `action_items` list.

## Per-field confidence

When downstream needs to route uncertain fields to a human, wrap each value in a confidence carrier.

```python theme={null}
from typing import Literal, Optional

from agno.agent import Agent
from agno.models.google import Gemini
from pydantic import BaseModel, Field


class ConfidentField(BaseModel):
    value: Optional[str] = None
    confidence: Literal["high", "medium", "low"] = Field(
        ..., description="Confidence in the extracted value"
    )


class Contact(BaseModel):
    name: ConfidentField
    email: ConfidentField
    company: ConfidentField


instructions = """\
Extract contact information from the input. For each field:
- value:      what the text shows; null if the field is missing
- confidence: high if explicit and unambiguous;
              medium if implied or partially formatted;
              low if guessed or ambiguous

Use exactly what the text shows. Do not normalize or paraphrase.
"""

confidence_agent = Agent(
    model=Gemini(id="gemini-3.5-flash"),
    instructions=instructions,
    output_schema=Contact,
)
```

Define the levels in the instructions. Without a rubric the model has nothing to anchor `high` against `medium`, and the confidence values come back arbitrary.

<Warning>
  OpenAI strict structured output rejects a `description` on a field whose type is itself a referenced model. Keep `Field(..., description=...)` off fields typed as a sub-model; put the explanation in a comment or the instructions instead.
</Warning>

## Any modality, same pattern

The input argument changes per modality. Use a model that supports both that modality and structured output. See [Multimodal inputs](/use-cases/data-labeling/multimodal-inputs) for the input arguments.

| Input | Argument                                    | Cookbook                                                                                                            |
| ----- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| Text  | `agent.run(text)`                           | [text\_extraction](https://github.com/agno-agi/agno/tree/v2.7.4/cookbook/data_labeling/_03_text_extraction)         |
| Image | `images=[Image(url=...)]`                   | [image\_extraction](https://github.com/agno-agi/agno/tree/v2.7.4/cookbook/data_labeling/_07_image_extraction)       |
| Audio | `audio=[Audio(content=...)]`                | [audio\_extraction](https://github.com/agno-agi/agno/tree/v2.7.4/cookbook/data_labeling/_12_audio_extraction)       |
| Video | `videos=[Video(content=..., format="mp4")]` | [video\_extraction](https://github.com/agno-agi/agno/tree/v2.7.4/cookbook/data_labeling/_14_video_extraction)       |
| PDF   | `files=[File(url=...)]`                     | [document\_extraction](https://github.com/agno-agi/agno/tree/v2.7.4/cookbook/data_labeling/_16_document_extraction) |

## Extract then embed

`image_extraction_to_vectordb` extends extraction with an embed-and-store step: describe each image into a typed object, flatten it to a searchable string, embed it, and store it in LanceDb for similarity search. See the [cookbook](https://github.com/agno-agi/agno/tree/v2.7.4/cookbook/data_labeling/_09_image_extraction_to_vectordb).

This recipe needs LanceDb on top of the Google provider:

```bash theme={null}
pip install lancedb tantivy
```

## Next steps

| Task                            | Guide                                                           |
| ------------------------------- | --------------------------------------------------------------- |
| Assign labels instead of fields | [Classification](/use-cases/data-labeling/classification)       |
| Feed non-text input             | [Multimodal inputs](/use-cases/data-labeling/multimodal-inputs) |
| Add a reviewer and adjudicator  | [Quality pipeline](/use-cases/data-labeling/quality-pipeline)   |

## Developer Resources

* [Text extraction cookbook](https://github.com/agno-agi/agno/tree/v2.7.4/cookbook/data_labeling/_03_text_extraction)
* [Structured output](/input-output/structured-output/agent)
