fern/docs/pages/api-guide/tools.mdx
PrivateGPT exposes tools in two ways:
tools array of /v1/messages and let the model decide when to call them./v1/tools/*) — call them directly without going through a chat.Pass tools in /v1/messages and the model decides when to call them.
Model-driven tool use follows the same per-tool dependency rules. For the broadest support, use private-gpt[tools] or private-gpt[core].
Built-in server tools only require name and type. Do not provide inputSchema for built-in tools. Add context only for built-in tools that require it.
| Type identifier | Tool | Notes |
|---|---|---|
semantic_search_v1 | Search ingested documents | Available in private-gpt[core] and installs with ingestion support |
tabular_analysis_v1 | Analyze ingested tabular data | Requires tool-tabular or tools |
database_query_v1 | Query a SQL database | Requires database extras |
web_search_v1 | Search the web | Requires tool-web-scraping or tools |
web_fetch_v1 | Fetch and extract text from a URL | Requires tool-web-scraping or tools |
Minimal example:
{
"tools": [
{"name": "search_docs", "type": "semantic_search_v1"},
{"name": "search_web", "type": "web_search_v1"},
{"name": "fetch_url", "type": "web_fetch_v1"}
]
}
For server-side setup of web tools, see Web Tools.
semantic_search_v1Requires context with an ingested artifact.
{
"model": "qwen3.5:35b",
"messages": [
{"role": "user", "content": "What are the payment terms in the contract?"}
],
"tools": [
{
"name": "search_docs",
"type": "semantic_search_v1",
"context": [
{
"type": "ingested_artifact",
"context_filter": {"collection": "contracts"}
}
]
}
]
}
tabular_analysis_v1Requires private-gpt[tool-tabular], private-gpt[tools], or private-gpt[core]. Also requires context with an ingested artifact.
{
"model": "qwen3.5:35b",
"messages": [
{"role": "user", "content": "What is the total revenue by region?"}
],
"tools": [
{
"name": "analyze_sales",
"type": "tabular_analysis_v1",
"context": [
{
"type": "ingested_artifact",
"context_filter": {"collection": "sales-data"}
}
]
}
]
}
database_query_v1Requires private-gpt[tool-database], private-gpt[database], or a driver-specific extra such as private-gpt[database-postgres]. private-gpt[tools] and private-gpt[core] also work. Also requires context with a sql_database artifact. See Database Tools for install and configuration.
{
"model": "qwen3.5:35b",
"messages": [
{"role": "user", "content": "How many orders were placed last month?"}
],
"tools": [
{
"name": "query_db",
"type": "database_query_v1",
"context": [
{
"type": "sql_database",
"connection_string": "postgresql://user:pass@localhost:5432/mydb",
"description": "Orders database"
}
]
}
]
}
Connection strings commonly use these schemes:
postgresql://...mysql://..., mysql+mysqldb://..., or mysql+pymysql://...mssql+pyodbc://...db2://... or ibm_db_sa://...Examples:
postgresql://user:pass@localhost:5432/mydb
mysql://user:pass@localhost:3306/mydb
mssql+pyodbc://user:pass@localhost:1433/mydb?driver=ODBC+Driver+18+for+SQL+Server
db2://user:pass@localhost:50000/sample
web_search_v1Requires private-gpt[tool-web-scraping], private-gpt[tools], or private-gpt[core]. No context is required.
{
"model": "qwen3.5:35b",
"messages": [
{"role": "user", "content": "Find recent news about open source LLMs."}
],
"tools": [
{
"name": "search_web",
"type": "web_search_v1"
}
]
}
web_fetch_v1web_extract_v1 remains accepted as a legacy alias.
Requires private-gpt[tool-web-scraping], private-gpt[tools], or private-gpt[core]. No context is required.
{
"model": "qwen3.5:35b",
"messages": [
{"role": "user", "content": "Fetch and summarize https://example.com/article"}
],
"tools": [
{
"name": "fetch_url",
"type": "web_fetch_v1"
}
]
}
The built-in skill tool is name: "skills" with type: "skills_v1". It expands into load_skill_v1, unload_skill_v1, and list_skills_v1.
These built-in skill tools require a skill filter in tool_context.
| Type identifier | Tool |
|---|---|
skills_v1 | Expand into load_skill_v1, unload_skill_v1, and list_skills_v1 |
load_skill_v1 | Mark one available skill as loaded |
unload_skill_v1 | Mark one loaded skill as unloaded |
list_skills_v1 | List skills in the current skill filter |
Example:
{
"model": "qwen3.5:35b",
"messages": [
{"role": "user", "content": "Show me the available skills for this workspace."}
],
"tool_context": [
{
"type": "skill",
"skill_filter": {"collection": "my-org"}
}
],
"tools": [
{"name": "skills", "type": "skills_v1"}
]
}
Direct load_skill_v1 example:
{
"model": "qwen3.5:35b",
"messages": [
{"role": "user", "content": "Load the legal-reviewer skill."}
],
"tool_context": [
{
"type": "skill",
"skill_filter": {"collection": "my-org"}
}
],
"tools": [
{"name": "load_skill", "type": "load_skill_v1"}
]
}
PrivateGPT exposes built-in code-execution tools in two layers:
code_execution_v1 expands into bash_v1 and text_editor_v1.text_editor_v1 expands into view_v1, str_replace_v1, create_v1, and insert_v1.These are built-in server tools executed by PrivateGPT.
code_execution_v1 is a server tool. Anthropic code_execution_* tool types translate to this server-side flow in PrivateGPT. That is different from Anthropic bash_* and text_editor_*, which are client tools passed back to the API caller.
Anthropic reference: Code execution tool.
code_execution_v1{
"model": "qwen3.5:35b",
"messages": [
{"role": "user", "content": "Inspect the workspace and tell me which files matter."}
],
"tools": [
{"name": "code_execution", "type": "code_execution_v1"}
]
}
bash_v1{
"model": "qwen3.5:35b",
"messages": [
{"role": "user", "content": "Run ls in the workspace."}
],
"tools": [
{"name": "bash", "type": "bash_v1"}
]
}
text_editor_v1{
"model": "qwen3.5:35b",
"messages": [
{"role": "user", "content": "Open README.md and inspect it."}
],
"tools": [
{"name": "text_editor", "type": "text_editor_v1"}
]
}
| Type identifier | Tool |
|---|---|
view_v1 | View a file or directory |
str_replace_v1 | Replace one exact string in a file |
create_v1 | Create a new file |
insert_v1 | Insert text after a given line |
PrivateGPT also accepts Anthropic-style client tool types. These are passed through to your application with canonical schemas; PrivateGPT does not execute them locally.
Supported client tool families:
| Type pattern | Canonical name | Executed by | More info |
|---|---|---|---|
bash_* | bash | API caller | Anthropic bash tool |
text_editor_* | str_replace_based_edit_tool | API caller | Anthropic text editor tool |
computer_* | computer | API caller | Anthropic computer use tool |
memory_* | memory | API caller | Anthropic memory tool |
Example:
{
"model": "claude-sonnet-4-20250514",
"messages": [
{"role": "user", "content": "Open README.md and show me the first 40 lines."}
],
"tools": [
{"name": "bash", "type": "bash_20250124"},
{"name": "str_replace_based_edit_tool", "type": "text_editor_20250124"},
{"name": "computer", "type": "computer_20250124"},
{"name": "memory", "type": "memory_20250124"}
]
}
Define any tool with a JSON Schema. PrivateGPT passes the tool definition to the model; when the model calls it, your application receives a tool_use block and must return a tool_result:
For the broadest tool-calling support, use private-gpt[tools] or private-gpt[core].
{
"tools": [
{
"name": "get_order_status",
"description": "Get the current status of a customer order",
"inputSchema": {
"type": "object",
"properties": {
"order_id": {"type": "string", "description": "The order ID"}
},
"required": ["order_id"]
}
}
]
}
When the model wants to call the tool, the response contains:
{"type": "tool_use", "id": "tu_01abc", "name": "get_order_status", "input": {"order_id": "ORD-123"}}
Send the result back by appending a message with role: "user" containing a tool_result block:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "tu_01abc",
"content": "Order ORD-123 is shipped and arrives Thursday."
}
]
}
Search ingested documents using natural language:
Available in private-gpt[core] and installs with ingestion support.
curl -X POST http://localhost:8080/v1/tools/semantic-search \
-H "Content-Type: application/json" \
-d '{
"query": "What are the payment terms?",
"context_filter": {"collection": "contracts"}
}'
Search the web and get aggregated results:
Requires private-gpt[tool-web-scraping], private-gpt[tools], or private-gpt[core].
curl -X POST http://localhost:8080/v1/tools/web-search \
-H "Content-Type: application/json" \
-d '{"query": "latest news about open source LLMs"}'
Fetch and extract text content from a URL:
Requires private-gpt[tool-web-scraping], private-gpt[tools], or private-gpt[core].
curl -X POST http://localhost:8080/v1/tools/web-fetch \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/article"}'
Run a natural language query against CSV or tabular data ingested into a collection:
Requires private-gpt[tool-tabular], private-gpt[tools], or private-gpt[core].
curl -X POST http://localhost:8080/v1/tools/tabular-data-analysis \
-H "Content-Type: application/json" \
-d '{
"query": "What is the total revenue by region?",
"context_filter": {"collection": "sales-data"}
}'
Run a natural language query against a connected SQL database:
Requires private-gpt[tool-database], private-gpt[database], or a driver-specific extra such as private-gpt[database-postgres]. private-gpt[tools] and private-gpt[core] also work. See Database Tools for install and configuration.
curl -X POST http://localhost:8080/v1/tools/database-query \
-H "Content-Type: application/json" \
-d '{
"query": "How many orders were placed last month?",
"artifacts": [
{
"type": "sql_database",
"connection_string": "postgresql://user:pass@localhost/mydb"
}
]
}'
The artifacts entry must contain a sql_database object with a valid SQLAlchemy-style connection string, for example:
postgresql://user:pass@localhost:5432/mydb
mysql://user:pass@localhost:3306/mydb
mssql+pyodbc://user:pass@localhost:1433/mydb?driver=ODBC+Driver+18+for+SQL+Server
db2://user:pass@localhost:50000/sample