Markdown Chunking

Split Markdown documents by heading structure or an approximate character target.

MarkdownChunking returns content at or below chunk_size as one chunk in its default mode. For longer content, it uses Unstructured to partition Markdown and group the resulting elements toward chunk_size. Set split_on_headings=True to split on every ATX heading from H1 through H6. Set an integer from 1 to 6 to split on ATX headings through that level.

Create a Python file

from agno.agent import Agent
from agno.knowledge.chunking.markdown import MarkdownChunking
from agno.knowledge.knowledge import Knowledge
from agno.knowledge.reader.markdown_reader import MarkdownReader
from agno.vectordb.pgvector import PgVector

db_url = "postgresql+psycopg://ai:ai@localhost:5532/ai"

knowledge = Knowledge(
    vector_db=PgVector(table_name="recipes_markdown_chunking", db_url=db_url),
)

knowledge.insert(
    url="https://raw.githubusercontent.com/agno-agi/agno/v2.7.2/README.md",
    reader=MarkdownReader(
        name="Markdown Chunking Reader",
        chunking_strategy=MarkdownChunking(chunk_size=1000),
    ),
)

agent = Agent(
    knowledge=knowledge,
    search_knowledge=True,
)

agent.print_response("What is Agno?", markdown=True)

Set up your virtual environment

uv venv --python 3.12
source .venv/bin/activate

Install dependencies

uv pip install -U agno sqlalchemy psycopg pgvector "unstructured<0.18.31" markdown openai

Export your OpenAI API key

Set OpenAI Key

Set your OPENAI_API_KEY as an environment variable. You can get one from OpenAI.

export OPENAI_API_KEY=sk-***

Run PgVector

docker run -d \
  -e POSTGRES_DB=ai \
  -e POSTGRES_USER=ai \
  -e POSTGRES_PASSWORD=ai \
  -e PGDATA=/var/lib/postgresql \
  -v pgvolume:/var/lib/postgresql \
  -p 5532:5432 \
  --name pgvector \
  agnohq/pgvector:18

Run the script

python markdown_chunking.py

Choose a Mode

split_on_headingsBehavior
FalseKeep short input as one chunk; partition and group longer input with Unstructured
TrueStart a chunk at every ATX heading from H1 through H6, regardless of document size
1 to 6Start a chunk at ATX headings through the selected level, regardless of document size

In heading mode, sections longer than chunk_size are split by paragraphs, then by words, and repeat an existing heading. A long indivisible word or prepended overlap can make the final chunk longer than chunk_size. Overlap is prepended without an added separator.

Markdown Chunking Params

ParameterTypeDefaultDescription
chunk_sizeint5000Approximate character target. Long atomic content and overlap can make final chunks larger.
overlapint0The number of characters to overlap between chunks.
split_on_headingsUnion[bool, int]FalseHeading-based splitting. False uses size-based chunking. True splits on all headings (H1-H6). An int from 1 to 6 splits on headings at or above that level, e.g. 2 splits on H1 and H2.

Developer Resources