Skip to content
TriedDocs
Knowledge bases

Create knowledge base

Create a knowledge base from uploaded files, text snippets and web pages.

POSThttps://api.tried.com.au/create-knowledge-base

Creates a knowledge base and starts ingesting its sources in the background. Attach it to an agent's LLM or flow through knowledge_base_ids so the agent can look up answers during calls and chats.

Embeddings use OpenAI text-embedding-3-small when OPENAI_API_KEY is set. Without it (or with TRIED_MOCK_PROVIDERS=1) Tried stores hash embeddings (mock-hash-256), so retrieval still works keyless with lower quality.

Request#

Send multipart/form-data to upload files, or application/json for texts and URLs only.

Field Type Required Description
knowledge_base_name string Yes 1 to 40 characters.
knowledge_base_texts array of objects No Text snippets, each { "title": string, "text": string }.
knowledge_base_urls array of strings No Web pages to fetch. Each must be a valid URL.
knowledge_base_files files No Documents to upload. Multipart only. See File types.
enable_auto_refresh boolean No Re-fetch URL sources about once a day. Default false.
chunk_size integer No Target characters per chunk. 200 to 4000, default 800.
chunk_overlap integer No Characters shared between neighbouring chunks. 0 to 1000, default 100. Must be smaller than chunk_size when you send both.
auto_add_pages boolean No On refresh, crawl crawl_roots and add pages that are not sources yet. Default false.
crawl_roots array of strings No Up to 10 site URLs to crawl when auto_add_pages is on.

In multipart requests, send arrays and objects as a JSON string (for example knowledge_base_texts=[{"title":"Hours","text":"..."}]) or repeat the field with a [] suffix (knowledge_base_urls[]=https://...). The strings true and false are read as booleans.

Limits#

  • Per request: up to 25 files, each at most 50 MB.
  • Per knowledge base: 25 files, 500 URLs and 50 text snippets. Synced sources do not count.
  • JSON bodies: at most 25 MB.

File types#

File How the text is read
PDF Text extraction with pdf.js. Scanned PDFs without a text layer give little or no text.
.docx Raw text of the document.
.xlsx, .xls Each sheet as CSV under a ## <sheet name> heading.
.pptx Text of each slide as Slide <n>: ....
Images (png, jpg, gif, bmp, tiff, webp) OCR with tesseract when it is installed on the API host. Otherwise the source holds a placeholder line that names the file.
Anything else (.txt, .md, .csv, .html, ...) Stored as UTF-8 text.

How ingestion works#

  1. Each source is saved and the knowledge base status becomes in_progress. The response returns at this point.
  2. URL sources are fetched (15 second timeout). HTML is converted to text, with scripts and styles removed.
  3. Text is split into chunks of about chunk_size characters, preferring paragraph and sentence breaks, with chunk_overlap characters of overlap.
  4. Chunks are embedded and stored. The knowledge base status becomes complete, or error if any source in the batch failed.

URL fetching#

URLs go through Tried's egress guard to prevent server-side request forgery:

  • Only http and https URLs are fetched.
  • Private, loopback, link-local, CGNAT, multicast, documentation and reserved addresses are refused. For IPv4 that is 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.0.0/24, 192.0.2.0/24, 192.168.0.0/16, 198.18.0.0/15, 198.51.100.0/24, 203.0.113.0/24, 224.0.0.0/4 and 240.0.0.0/4. For IPv6 it is ::, ::1, fc00::/7, fe80::/10, ff00::/8, 2001:db8::/32, 64:ff9b::/96 and 100::/64. IPv4-mapped IPv6 addresses are checked against the IPv4 list.
  • The check runs on the address the socket actually connects to, so a hostname cannot pass the check and then resolve to a private address (DNS rebinding).
  • Redirects are followed by Tried, up to 5 hops, and every hop is checked again.

A refused or failing URL marks that source as failed and the knowledge base status as error. Self-hosted installs can turn the address check off with EGRESS_ALLOW_PRIVATE=1 for local development only.

Example request#

curl -X POST https://api.tried.com.au/create-knowledge-base \
  -H "Authorization: Bearer $TRIED_API_KEY" \
  -F knowledge_base_name="Clinic FAQ" \
  -F 'knowledge_base_texts=[{"title":"Opening hours","text":"We are open 8am to 6pm, Monday to Saturday."}]' \
  -F 'knowledge_base_urls[]=https://example.com.au/pricing' \
  -F knowledge_base_files=@price-list.pdf
import { readFile } from "node:fs/promises";

const form = new FormData();
form.append("knowledge_base_name", "Clinic FAQ");
form.append("knowledge_base_texts", JSON.stringify([
  { title: "Opening hours", text: "We are open 8am to 6pm, Monday to Saturday." },
]));
form.append("knowledge_base_urls[]", "https://example.com.au/pricing");
form.append("knowledge_base_files", new Blob([await readFile("price-list.pdf")], { type: "application/pdf" }), "price-list.pdf");

const res = await fetch("https://api.tried.com.au/create-knowledge-base", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.TRIED_API_KEY}` },
  body: form,
});
const kb = await res.json();
import json, os, requests

with open("price-list.pdf", "rb") as f:
    res = requests.post(
        "https://api.tried.com.au/create-knowledge-base",
        headers={"Authorization": f"Bearer {os.environ['TRIED_API_KEY']}"},
        data={
            "knowledge_base_name": "Clinic FAQ",
            "knowledge_base_texts": json.dumps([
                {"title": "Opening hours", "text": "We are open 8am to 6pm, Monday to Saturday."}
            ]),
            "knowledge_base_urls[]": "https://example.com.au/pricing",
        },
        files=[("knowledge_base_files", ("price-list.pdf", f, "application/pdf"))],
    )
kb = res.json()

Without files, a JSON body works too:

{
  "knowledge_base_name": "Clinic FAQ",
  "knowledge_base_texts": [{ "title": "Opening hours", "text": "We are open 8am to 6pm, Monday to Saturday." }],
  "knowledge_base_urls": ["https://example.com.au/pricing"],
  "enable_auto_refresh": true,
  "chunk_size": 1200,
  "chunk_overlap": 150
}

Response#

201 Created

{
  "knowledge_base_id": "knowledge_base_9f060d81a4d8df9b04ca6d12",
  "knowledge_base_name": "Clinic FAQ",
  "status": "in_progress",
  "knowledge_base_sources": [
    {
      "source_id": "source_92055d142a2829e5c8e77a9f",
      "type": "text",
      "title": "Opening hours",
      "url": null,
      "content_url": "https://api.tried.com.au/get-knowledge-base-source-content/knowledge_base_9f060d81a4d8df9b04ca6d12/source_92055d142a2829e5c8e77a9f"
    },
    {
      "source_id": "source_21ce463cc228d0ea2a439493",
      "type": "url",
      "title": "https://example.com.au/pricing",
      "url": "https://example.com.au/pricing",
      "content_url": "https://api.tried.com.au/get-knowledge-base-source-content/knowledge_base_9f060d81a4d8df9b04ca6d12/source_21ce463cc228d0ea2a439493"
    },
    {
      "source_id": "source_5da4e4744cb7ea63832e856c",
      "type": "document",
      "title": "price-list.pdf",
      "url": null,
      "content_url": "https://api.tried.com.au/get-knowledge-base-source-content/knowledge_base_9f060d81a4d8df9b04ca6d12/source_5da4e4744cb7ea63832e856c"
    }
  ],
  "enable_auto_refresh": false,
  "last_refreshed_timestamp": null,
  "chunk_size": 800,
  "chunk_overlap": 100,
  "auto_add_pages": false,
  "crawl_roots": []
}

The fields are described in Get knowledge base. Poll that endpoint until status is complete or error.

Errors#

Status When
400 A field fails validation, chunk_overlap must be smaller than chunk_size, a per knowledge base limit is reached (A knowledge base holds at most 25 files, ... 500 URLs, ... 50 text snippets), or a file cannot be parsed (Could not read <filename>: ...).
401 Missing or invalid API key.
403 The key's IP allowlist or scopes reject the request (this route needs the kb scope), or the caller is a read-only dashboard member.
413 A file is over 50 MB, the request has more than 25 files, or a JSON body is over 25 MB.
429 Rate limit exceeded. See Rate limits.

See Errors for the body format.

Retell compatibility#

Same path and method as Retell, and the same knowledge_base_name, knowledge_base_texts, knowledge_base_urls, knowledge_base_files and enable_auto_refresh fields. Chunking differs: Tried takes chunk_size and chunk_overlap instead of Retell's max_chunk_size and min_chunk_size. Source objects carry title, url and content_url for every type.