API reference¶
Factories¶
deep_wiki_agent.factory.create_wiki_manager_agent ¶
create_wiki_manager_agent(
*,
model: str | BaseChatModel,
wiki_path: str | Path | None = None,
backend: BackendProtocol | None = None,
create_if_missing: bool = True,
protect_raw: bool = True,
enable_lint_tool: bool = True,
virtual_mode: bool = True,
embeddings: Embeddings | None = None,
vector_store: VectorStore | None = None,
search_k: int = 5,
semantic_config: SemanticConfig | None = None,
system_prompt: str | SystemMessage | None = None,
tools: Sequence[BaseTool] = (),
permissions: list[FilesystemPermission] | None = None,
middleware: Sequence[AgentMiddleware] = (),
**create_deep_agent_kwargs: Any,
) -> CompiledStateGraph
Create an agent that builds and maintains an OKF wiki.
The returned deep agent has read/write access to the bundle at
wiki_path. Its operating instructions — bundle structure, frontmatter
conformance, and the ingest / query / lint / bootstrap workflows — are in
its system prompt, so they are in force from the first turn with nothing to
load and nothing that can be skipped.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
str | BaseChatModel
|
Model for the agent. Required — either a provider string
(e.g. |
required |
wiki_path
|
str | Path | None
|
Local directory of the OKF bundle, placed at the virtual
root. Required unless |
None
|
backend
|
BackendProtocol | None
|
Pre-built backend, used verbatim instead of the one this
factory would assemble. Use it for non-local storage (state,
store, sandbox). Mutually exclusive with |
None
|
create_if_missing
|
bool
|
When |
True
|
protect_raw
|
bool
|
When |
True
|
enable_lint_tool
|
bool
|
When |
True
|
virtual_mode
|
bool
|
Confine the filesystem backend to the bundle directory,
blocking |
True
|
embeddings
|
Embeddings | None
|
Embedding model enabling semantic search. Given together
with |
None
|
vector_store
|
VectorStore | None
|
Store the chunks are written to and searched in. A store configured for hybrid retrieval (dense + BM25) keeps its keyword half — the query reaches it as text rather than as a vector. |
None
|
search_k
|
int
|
Default number of passages a semantic search returns. |
5
|
semantic_config
|
SemanticConfig | None
|
Index configuration — chunking, which directories may
be indexed, batch sizes, the manifest location. Defaults to
:class: |
None
|
system_prompt
|
str | SystemMessage | None
|
Override for the built-in manager prompt. Overriding it replaces the OKF instructions wholesale, so restate whatever of them you still want in force; the rest of the wiring is unchanged. |
None
|
tools
|
Sequence[BaseTool]
|
Extra tools, added alongside |
()
|
permissions
|
list[FilesystemPermission] | None
|
Override for the computed filesystem permissions. Passing
this replaces the |
None
|
middleware
|
Sequence[AgentMiddleware]
|
Extra middleware passed through to |
()
|
**create_deep_agent_kwargs
|
Any
|
Any remaining |
{}
|
Returns:
| Type | Description |
|---|---|
CompiledStateGraph
|
The compiled deep agent graph, ready for |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
FileNotFoundError
|
If |
deep_wiki_agent.factory.create_deep_wiki_agent ¶
create_deep_wiki_agent(
*,
model: str | BaseChatModel,
wiki_path: str | Path | None = None,
backend: BackendProtocol | None = None,
not_found_message: str = DEFAULT_NOT_FOUND_MESSAGE,
structured_output: bool = False,
virtual_mode: bool = True,
embeddings: Embeddings | None = None,
vector_store: VectorStore | None = None,
search_k: int = 5,
semantic_config: SemanticConfig | None = None,
system_prompt: str | SystemMessage | None = None,
tools: Sequence[BaseTool] = (),
permissions: list[FilesystemPermission] | None = None,
middleware: Sequence[AgentMiddleware] = (),
**create_deep_agent_kwargs: Any,
) -> CompiledStateGraph
Create an agent that answers questions from an existing OKF wiki.
The returned deep agent is read-only over the bundle: every write
operation is denied by FilesystemMiddleware at the tool boundary, not
merely discouraged by the prompt, so a consultation session cannot corrupt
the knowledge base regardless of what the model is asked to do.
Its answering contract is closed-book over the bundle: it navigates the
indexes and the link graph following the query protocol in its prompt,
cites the pages it used, and — when the bundle does not cover the question
— replies with not_found_message instead of falling back on the model's
own knowledge.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
str | BaseChatModel
|
Model for the agent. Required — either a provider string
(e.g. |
required |
wiki_path
|
str | Path | None
|
Local directory of the OKF bundle to consult, placed at the
virtual root. Required unless |
None
|
backend
|
BackendProtocol | None
|
Pre-built backend, used verbatim instead of the one this
factory would assemble — for a bundle held in a store, a sandbox,
or any non-local storage. Mutually exclusive with |
None
|
not_found_message
|
str
|
The exact sentence the agent must return when the bundle does not contain the requested information. Override it to match your product's voice or language; the surrounding contract (no guessing, no outside knowledge, partial answers allowed and labelled) is unchanged. |
DEFAULT_NOT_FOUND_MESSAGE
|
structured_output
|
bool
|
When |
False
|
virtual_mode
|
bool
|
Confine the filesystem backend to the bundle directory,
blocking |
True
|
embeddings
|
Embeddings | None
|
Embedding model enabling semantic search. Given together
with |
None
|
vector_store
|
VectorStore | None
|
Store holding the index to search. Must be the one the bundle was ingested into: this agent never writes to it. |
None
|
search_k
|
int
|
Default number of passages a semantic search returns. |
5
|
semantic_config
|
SemanticConfig | None
|
Index configuration. Only its search-side fields
matter here ( |
None
|
system_prompt
|
str | SystemMessage | None
|
Override for the built-in reader prompt. Note that the
not-found contract, the query protocol and the field-filling
instructions |
None
|
tools
|
Sequence[BaseTool]
|
Extra read-only tools. Do not pass tools that can write to the bundle: the filesystem permissions cannot police tools they do not mediate. |
()
|
permissions
|
list[FilesystemPermission] | None
|
Override for the read-only permission set. Passing this replaces the deny-all-writes rule — the agent is then only as read-only as your rules make it. |
None
|
middleware
|
Sequence[AgentMiddleware]
|
Extra middleware passed through to |
()
|
**create_deep_agent_kwargs
|
Any
|
Any remaining |
{}
|
Returns:
| Type | Description |
|---|---|
CompiledStateGraph
|
The compiled deep agent graph, ready for |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
FileNotFoundError
|
If |
Structured responses¶
deep_wiki_agent.schemas.WikiAnswer ¶
Bases: BaseModel
A reader agent's answer, as data rather than prose.
The field descriptions are part of the schema handed to the model, so they are written as instructions to it rather than as notes to the reader of this file.
Opt in with create_deep_wiki_agent(..., structured_output=True). The answer
then arrives as a WikiAnswer under result["structured_response"], and the
reader's prompt gains a section explaining how the fields map onto the
not-found contract.
The value is that found is False replaces a string comparison against
not_found_message, which stops being a reliable test the moment the message
is reworded or translated. The cost is the model's freedom to shape a prose
answer to the question, which is why free text remains the default.
The flag sets response_format on the underlying deep agent, so it is mutually
exclusive with passing response_format yourself — a ValueError if you pass
both. Passing your own schema that way remains supported, and skips the prompt
section, since that section describes WikiAnswer's fields specifically.
Permissions¶
deep_wiki_agent.backends.read_only_permissions ¶
Deny every write on the whole virtual filesystem.
Enforced by FilesystemMiddleware at the tool boundary, so it holds even
if the model is talked into ignoring its system prompt.
Returns:
| Type | Description |
|---|---|
list[FilesystemPermission]
|
A one-rule permission list denying |
deep_wiki_agent.backends.write_protect_permissions ¶
Deny writes under the given path prefixes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
paths
|
list[str]
|
Directory paths to protect, e.g. |
required |
Returns:
| Type | Description |
|---|---|
list[FilesystemPermission]
|
A one-rule permission list suitable for |
list[FilesystemPermission]
|
empty list when |
list[FilesystemPermission]
|
restrict nothing while still looking like a restriction. |
Linting¶
deep_wiki_agent.tools.lint.create_okf_lint_tool ¶
create_okf_lint_tool(
wiki_path: str | Path | None = None,
*,
backend: BackendProtocol | None = None,
) -> BaseTool
Build an okf_lint tool bound to one bundle.
The bundle — a local directory or a pre-built backend — is captured in the
closure rather than taken as a tool argument, so the model cannot point the
linter (and its fix writes) at an arbitrary location.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wiki_path
|
str | Path | None
|
Directory of the bundle this tool validates, on the local
filesystem. Mutually exclusive with |
None
|
backend
|
BackendProtocol | None
|
A pre-built deepagents backend (state, store, sandbox, or
filesystem) holding the bundle this tool validates. Mutually
exclusive with |
None
|
Returns:
| Type | Description |
|---|---|
BaseTool
|
A tool taking a single optional |
BaseTool
|
plain-text conformance report. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither or both of |
deep_wiki_agent.tools.lint.run_okf_lint ¶
run_okf_lint(
wiki_path: str | Path | None = None,
*,
backend: BackendProtocol | None = None,
fix: bool = False,
) -> dict[str, Any]
Validate an OKF bundle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wiki_path
|
str | Path | None
|
Directory of the bundle to validate, on the local
filesystem. Mutually exclusive with |
None
|
backend
|
BackendProtocol | None
|
A pre-built deepagents backend (state, store, sandbox, or
filesystem) holding the bundle, validated in place through its
|
None
|
fix
|
bool
|
When |
False
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
A dict with |
dict[str, Any]
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither or both of |
NotADirectoryError
|
If |
RuntimeError
|
If a backend operation the linter needs fails. |
deep_wiki_agent.okf_lint.lint ¶
Validate an OKF bundle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path | Backend
|
Bundle root directory, or an object implementing :class: |
required |
fix
|
bool
|
When |
False
|
Returns:
| Type | Description |
|---|---|
LintReport
|
An |
LintReport
|
|
LintReport
|
bundle-relative path. |
Source documents¶
Both require the optional documents extra
(pip install "deep-wiki-agent[documents]"), which pulls in
markitdown. Without it, the module
still imports — the dependency is loaded inside the converter — and a
conversion attempt raises ImportError with the install command.
deep_wiki_agent.tools.documents.create_read_document_tool ¶
create_read_document_tool(
wiki_path: str | Path | None = None,
*,
backend: BackendProtocol | None = None,
root: str = RAW_DIR,
max_chars: int = DEFAULT_MAX_CHARS,
virtual_mode: bool = True,
) -> BaseTool
Build a read_document tool bound to one bundle.
Pass the result to a factory's tools::
from deep_wiki_agent import (
create_read_document_tool,
create_wiki_manager_agent,
)
manager = create_wiki_manager_agent(
model="anthropic:claude-sonnet-5",
wiki_path="./my-wiki",
tools=[create_read_document_tool("./my-wiki")],
)
The bundle is captured in the closure and reads are confined to root,
so the only thing the model chooses is which source document to open.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wiki_path
|
str | Path | None
|
Directory of the bundle this tool reads from, on the local
filesystem. Mutually exclusive with |
None
|
backend
|
BackendProtocol | None
|
A pre-built deepagents backend (state, store, sandbox, or
filesystem) holding the bundle. Mutually exclusive with
|
None
|
root
|
str
|
Directory reads are confined to. Defaults to |
RAW_DIR
|
max_chars
|
int
|
Truncate the returned markdown beyond this many characters, appending a note saying so. Guards the context window against a single oversized source. |
DEFAULT_MAX_CHARS
|
virtual_mode
|
bool
|
Confine the assembled filesystem backend to
|
True
|
Returns:
| Type | Description |
|---|---|
BaseTool
|
A tool taking a single |
BaseTool
|
markdown, or an |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither or both of |
NotADirectoryError
|
If |
deep_wiki_agent.tools.documents.read_document ¶
read_document(
path: str,
*,
wiki_path: str | Path | None = None,
backend: BackendProtocol | None = None,
root: str = RAW_DIR,
) -> str
Read a source document from the bundle and return it as markdown.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Path of the document, relative to |
required |
wiki_path
|
str | Path | None
|
Directory of the bundle holding the document, on the local
filesystem. Mutually exclusive with |
None
|
backend
|
BackendProtocol | None
|
A pre-built deepagents backend (state, store, sandbox, or
filesystem) holding the bundle. Mutually exclusive with
|
None
|
root
|
str
|
Directory reads are confined to. Defaults to |
RAW_DIR
|
Returns:
| Type | Description |
|---|---|
str
|
The document converted to markdown, in full — unlike the tool built by |
str
|
func: |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither or both of |
NotADirectoryError
|
If |
ImportError
|
If the optional |
RuntimeError
|
If the document cannot be read or converted. |
Semantic search¶
All of the following require the optional semantic extra
(pip install "deep-wiki-agent[semantic]"), which brings
langchain-text-splitters and includes the documents extra — ingestion has
to read whatever sits in raw/, and a PDF there is the common case. No vector
store is pinned: pass any LangChain VectorStore.
Enabling it is a matter of handing embeddings and vector_store to either
factory. The manager then gets semantic_ingest and semantic_search; the
reader gets semantic_search alone, since the ingestion tool writes and that
agent is read-only by construction. Both gain the prompt section that explains
their half — for the reader, that a hit is an entry point rather than an
answer, and that citations name the page and never the excerpt.
deep_wiki_agent.semantic.tools.create_semantic_tools ¶
create_semantic_tools(
embeddings: Embeddings,
vector_store: VectorStore,
*,
wiki_path: str | Path | None = None,
backend: BackendProtocol | None = None,
search_k: int = 5,
config: SemanticConfig | None = None,
virtual_mode: bool = True,
) -> SemanticTools
Build the ingestion and search tools for one bundle and one store.
Pass the result's tools to a factory, or let
:func:~deep_wiki_agent.factory.create_wiki_manager_agent build them for
you by handing it embeddings and vector_store directly::
from deep_wiki_agent import create_semantic_tools
semantic = create_semantic_tools(
OpenAIEmbeddings(model="text-embedding-3-small"),
QdrantVectorStore(...),
wiki_path="./my-wiki",
)
semantic.ingest() # deterministic, no agent involved
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
embeddings
|
Embeddings
|
Embedding model for the chunks and the queries. |
required |
vector_store
|
VectorStore
|
Store the chunks are written to and searched in. A store configured for hybrid retrieval keeps its keyword half: the query reaches it as text rather than as a vector. |
required |
wiki_path
|
str | Path | None
|
Directory of the bundle, on the local filesystem. Mutually
exclusive with |
None
|
backend
|
BackendProtocol | None
|
A pre-built deepagents backend (state, store, sandbox or
filesystem) holding the bundle. Mutually exclusive with
|
None
|
search_k
|
int
|
Default number of passages a search returns. |
5
|
config
|
SemanticConfig | None
|
Index configuration — chunking, the directories ingestion may
read, batch sizes, the manifest location. Defaults to
:class: |
None
|
virtual_mode
|
bool
|
Confine the assembled filesystem backend to
|
True
|
Returns:
| Type | Description |
|---|---|
SemanticTools
|
The two tools and the index they drive. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither or both of |
NotADirectoryError
|
If |
deep_wiki_agent.semantic.tools.ingest_semantic_index ¶
ingest_semantic_index(
embeddings: Embeddings,
vector_store: VectorStore,
*,
wiki_path: str | Path | None = None,
backend: BackendProtocol | None = None,
patterns: Sequence[str] | None = None,
tags: Sequence[str] | None = None,
only_modified: bool = True,
config: SemanticConfig | None = None,
virtual_mode: bool = True,
) -> IngestReport
Index a bundle without an agent in the loop.
The same code path the semantic_ingest tool runs, exposed for a
deterministic job — a cron entry, a post-commit hook, the rebuild step of a
deployment — where nothing should depend on a model deciding to call a tool.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
embeddings
|
Embeddings
|
Embedding model for the chunks. |
required |
vector_store
|
VectorStore
|
Store the chunks are written to. |
required |
wiki_path
|
str | Path | None
|
Directory of the bundle, on the local filesystem. Mutually
exclusive with |
None
|
backend
|
BackendProtocol | None
|
A pre-built deepagents backend holding the bundle. Mutually
exclusive with |
None
|
patterns
|
Sequence[str] | None
|
Files, directories or globs to index. Defaults to the whole bundle. |
None
|
tags
|
Sequence[str] | None
|
Labels stored with every chunk this call indexes. |
None
|
only_modified
|
bool
|
Skip files that have not changed since the last run. |
True
|
config
|
SemanticConfig | None
|
Index configuration. |
None
|
virtual_mode
|
bool
|
Confine the assembled filesystem backend to |
True
|
Returns:
| Type | Description |
|---|---|
IngestReport
|
What the run did, as an |
IngestReport
|
class: |
Raises:
| Type | Description |
|---|---|
ValueError
|
If neither or both of |
NotADirectoryError
|
If |
deep_wiki_agent.semantic.tools.SemanticTools
dataclass
¶
The tools of one index, plus the functions underneath them.
Attributes:
| Name | Type | Description |
|---|---|---|
ingest_tool |
BaseTool
|
The |
search_tool |
BaseTool
|
The |
index |
SemanticIndex
|
The :class: |
ingest
property
¶
ingest: Callable[..., IngestReport]
The ingestion function, without the tool wrapper.
search
property
¶
The search function, without the tool wrapper.
deep_wiki_agent.semantic.index.SemanticConfig
dataclass
¶
Everything about the index that the model does not get to choose.
Attributes:
| Name | Type | Description |
|---|---|---|
chunking |
ChunkingConfig
|
How a page is cut into chunks. |
ingest_roots |
tuple[str, ...]
|
Directories ingestion is confined to. A pattern that resolves outside them is dropped — the patterns can come from the model, the roots cannot. |
text_extensions |
tuple[str, ...]
|
Suffixes read as text through the backend. |
document_extensions |
tuple[str, ...]
|
Suffixes converted with |
max_files_per_call |
int
|
Ceiling on the files one ingest touches. When it trips, stale-chunk pruning is skipped for that call: a partial scan cannot tell a deleted file from one it never reached. |
batch_size |
int
|
Documents per |
deterministic_ids |
bool
|
Derive each chunk's id from its page, section and position, so re-ingesting a file updates its chunks instead of duplicating them. Turn it off only for a store that assigns ids itself, and accept that incremental ingest degrades with it. |
trust_timestamps |
bool
|
Skip downloading a file whose size and modification time both match the manifest. Saves re-reading large sources; turn it off when a backend's timestamps are too coarse to trust. |
over_fetch |
int
|
Multiplier on |
snippet_chars |
int
|
Longest snippet per hit in the text handed to the model. The full chunk always travels in the tool's artifact. |
corpus_name |
str | None
|
Label written into every chunk's metadata. |
filter_builder |
Callable[[dict[str, Any]], Any] | None
|
Converts the active filters into the store's own filter
object, for server-side filtering. Left |
manifest_path |
str
|
Where the ingest manifest is kept, on the bundle's
virtual filesystem. The default sits under a dot-directory, so the
linter (which walks |
deep_wiki_agent.semantic.index.IngestReport
dataclass
¶
What one ingest did.
Attributes:
| Name | Type | Description |
|---|---|---|
files |
int
|
Files whose chunks were written. |
skipped |
int
|
Files left alone because they had not changed. |
chunks |
int
|
Chunks written. |
table_chunks |
int
|
How many of those chunks are tables. |
deleted |
int
|
Chunks removed from the store — superseded by a re-ingest, or belonging to a file that is gone. |
matched_files |
list[str]
|
Paths of the files that were ingested. |
errors |
list[str]
|
Per-file failures, as |
truncated |
bool
|
Whether |
deep_wiki_agent.semantic.chunking.ChunkingConfig
dataclass
¶
How a page is cut into chunks.
Fixed when the tools are built, never exposed to the model: chunk sizes are a property of the index, and an agent that could change them per call would produce an index whose parts do not compare.
Attributes:
| Name | Type | Description |
|---|---|---|
headers_to_split_on |
tuple[tuple[str, str], ...]
|
|
chunk_size |
int
|
Target size, in characters, of a prose chunk. |
chunk_overlap |
int
|
Characters repeated between adjacent prose chunks, so a sentence cut in two is still retrievable from either side. |
prepend_header_path |
bool
|
Put the heading hierarchy at the top of each chunk's text. Costs a few tokens and buys a chunk that reads as self-contained once it is out of its page. |
extract_tables |
bool
|
Index GFM tables as atomic chunks instead of letting the character splitter cut them. |
table_max_chars |
int
|
Size past which a table is split, repeating its header and separator rows in every part. |
deep_wiki_agent.semantic.index.SemanticIndex ¶
Ingestion and search over one bundle and one vector store.
The bundle (through its backend), the embedding model, the store and the configuration are all fixed at construction. What a caller — or a model through a tool — chooses per call is only which files to ingest and what to search for.
__init__ ¶
__init__(
embeddings: Embeddings,
vector_store: VectorStore,
backend: BackendProtocol,
*,
search_k: int = 5,
config: SemanticConfig | None = None,
) -> None
Bind an index to a bundle and a store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
embeddings
|
Embeddings
|
Embedding model. Used directly only for a dense-only store, where embedding the query here avoids a round trip. |
required |
vector_store
|
VectorStore
|
Where the chunks live. Hybrid dense + BM25 stores are detected and driven through their text query path, so the keyword half is not silently dropped. |
required |
backend
|
BackendProtocol
|
Backend holding the bundle. Every read goes through it. |
required |
search_k
|
int
|
Default number of results a search returns. |
5
|
config
|
SemanticConfig | None
|
Index configuration. Defaults to :class: |
None
|
ingest ¶
ingest(
patterns: Sequence[str] | None = None,
*,
tags: Sequence[str] | None = None,
only_modified: bool = True,
) -> IngestReport
Index the bundle, or the part of it the patterns name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
patterns
|
Sequence[str] | None
|
Directories, file paths or globs to index. Defaults to
the configured |
None
|
tags
|
Sequence[str] | None
|
Labels written into every chunk's metadata, to filter searches by later. |
None
|
only_modified
|
bool
|
Skip files whose content has not changed since the
last ingest. Pass |
True
|
Returns:
| Type | Description |
|---|---|
IngestReport
|
What the run did, as an :class: |
search ¶
search(
query: str,
*,
k: int | None = None,
area: str = "any",
content_type: str = "any",
path_contains: str | None = None,
section_contains: str | None = None,
) -> list[dict[str, Any]]
Find the passages closest to a query.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
str
|
What to look for, in natural language. Both halves of the search see it: the dense one embeds it, and the lexical one — when the store is hybrid — matches its terms. |
required |
k
|
int | None
|
How many results to return. Defaults to the index's |
None
|
area
|
str
|
|
'any'
|
content_type
|
str
|
|
'any'
|
path_contains
|
str | None
|
Restrict to files whose path contains this substring. |
None
|
section_contains
|
str | None
|
Restrict to sections whose heading path contains this substring. |
None
|
Returns:
| Type | Description |
|---|---|
list[dict[str, Any]]
|
One dict per hit — rank, score, text, file, section, content type |
list[dict[str, Any]]
|
and the full chunk metadata — ordered best first. |
Constants¶
| Name | Value | Meaning |
|---|---|---|
WIKI_ROOT |
"/" |
mount point of the OKF bundle |
RAW_DIR |
"/raw" |
the immutable source-document directory |
BUNDLE_SKELETON |
see below | the layout the manager bootstraps |
DEFAULT_NOT_FOUND_MESSAGE |
see below | the reader's not-found answer |
BUNDLE_SKELETON = (
"AGENTS.md",
"raw/",
"wiki/index.md",
"wiki/log.md",
"wiki/assets/",
"wiki/documents/",
"wiki/entities/",
"wiki/concepts/",
"wiki/syntheses/",
)
DEFAULT_NOT_FOUND_MESSAGE = (
"I could not find the requested information in the wiki knowledge base."
)
BUNDLE_SKELETON is the same layout section 1 of both prompts draws, as
bundle-relative paths — directories carry a trailing slash, and each category
directory also holds its own index.md. Use it to pre-create a bundle, or to
check one you were handed; tests/test_prompt_paths.py uses it to verify that
every path the prompts cite exists in the layout they describe.
Prompt templates¶
MANAGER_SYSTEM_PROMPT_TEMPLATE and READER_SYSTEM_PROMPT_TEMPLATE carry the
agents' full operating instructions — bundle layout, frontmatter conformance,
the workflows. They are exported so you can inspect or extend them rather than
rewriting from scratch. They are str.format templates:
| Template | Placeholders |
|---|---|
MANAGER_SYSTEM_PROMPT_TEMPLATE |
wiki_root, raw_dir, lint_block, semantic_block |
READER_SYSTEM_PROMPT_TEMPLATE |
wiki_root, raw_dir, not_found_message, semantic_block, structured_output_block |
lint_block is filled with LINT_TOOL_BLOCK when the okf_lint tool is
attached, and with an empty string otherwise. semantic_block and
structured_output_block work the same way: SEMANTIC_MANAGER_BLOCK /
SEMANTIC_READER_BLOCK when semantic search is enabled, and
STRUCTURED_OUTPUT_BLOCK_TEMPLATE when structured_output=True, empty strings
otherwise. The blocks are plain strings, so an omitted one costs the agent
nothing.
STRUCTURED_OUTPUT_BLOCK_TEMPLATE is itself a str.format template taking
wiki_root and raw_dir — render it before substituting it in, since
str.format does not recurse into the values it interpolates.
from deep_wiki_agent import READER_SYSTEM_PROMPT_TEMPLATE
prompt = (
READER_SYSTEM_PROMPT_TEMPLATE.format(
wiki_root="/",
raw_dir="/raw",
not_found_message="Nothing found in the knowledge base.",
structured_output_block="",
)
+ "\n\nAlways answer in Italian."
)
Warning
Passing system_prompt to either factory replaces the built-in
instructions wholesale — for the reader, that includes the not-found
contract and the query protocol, so restate what you still want in force.
The read-only enforcement is separate: it lives in the filesystem
permissions and survives any prompt.
Migrating from 0.1.x¶
| Removed | Replacement |
|---|---|
build_wiki_backend |
FilesystemBackend(root_dir=wiki_path, virtual_mode=True) |
normalize_mount |
— |
bundled_skills_dir, okf_wiki_skill_dir, okf_lint_script |
— |
OKF_WIKI_SKILL_NAME, DEFAULT_SKILLS_MOUNT |
— |
skills_mount, skills_dir, extra_skills |
system_prompt= to change the instructions; create_deep_agent's own skills= passthrough for genuinely extra skills |
scripts/okf_lint.py inside the installed skill |
the okf-lint console script, or python -m deep_wiki_agent.okf_lint |