Skip to main content

Knowledge Base

A knowledge base gives your Agent private background knowledge: once your product docs, FAQs, or internal materials are connected, the Agent retrieves relevant content first and answers based on what it found, instead of relying only on the model's general knowledge.

In CloudBase, a knowledge base is connected to an Agent as an MCP tool: the retrieval service exposes an MCP server, the Agent declares that server in agent.yaml, and retrieval becomes callable during a conversation.

This page follows the actual order of work: pull the code, deploy the retrieval service, write the configuration, deploy, verify.

Prerequisites

Step 1: Pull the Agent code

On the Agent detail page in the console, follow the instructions on the Local development tab to pull the code:

Agent local development tab

You can also pull it with the CLI, where <function-name> is the cloud function backing the Agent:

tcb fn code download <function-name> ./agent-code -e <env-id>

Project structure:

agent-code/
├── agent.yaml # Agent configuration, see Step 3
├── package.json
├── scf_bootstrap # Cloud function startup script
├── dist/ # Build output
├── node_modules/
└── src/
├── index.ts # HTTP entry point, listens on port 9000 by default
├── config.ts # Configuration loading
├── managed/
└── oak-runtime/

Step 2: Deploy the knowledge base MCP server

The knowledge base MCP server is a standalone HTTP service — Cloud Run, a cloud function, or any reachable address works. Here is a minimal implementation using @modelcontextprotocol/sdk in stateless mode:

import express from "express";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { z } from "zod";

function buildServer() {
const server = new McpServer({ name: "kb", version: "1.0.0" });
server.tool(
"search",
"Search the knowledge base. Use when the user asks product-specific questions.",
{ query: z.string().describe("Search keywords") },
async (args) => {
const hits = await searchKnowledge(args.query); // Replace with your own retrieval, see "Implementing retrieval" below
if (hits.length === 0) return { content: [{ type: "text", text: "No relevant documents found." }] };
return { content: [{ type: "text", text: hits.map((d) => `[${d.id}] ${d.title}\n${d.content}`).join("\n---\n") }] };
},
);
return server;
}

const app = express();
app.use(express.json());

app.post("/mcp", async (req, res) => {
// Stateless mode: build a new server + transport per request; handleRequest must receive req.body as its third argument
const server = buildServer();
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
res.on("close", () => { transport.close(); server.close(); });
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
});

app.listen(Number(process.env.PORT ?? 8080));

After deploying, check that the tool is registered. The Streamable HTTP protocol requires the Accept: application/json, text/event-stream header — omitting either value returns a 406:

curl -X POST https://your-kb-service.example.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

The response should include the search tool.

Implementing retrieval

How you implement searchKnowledge is up to you. Common choices:

  • CloudBase database: split documents into chunks, store them with their vectors in the CloudBase database (PostgreSQL), and retrieve by vector similarity
  • An existing Elasticsearch or other search service: forward the query from inside searchKnowledge
  • Small knowledge sets (a few dozen entries): a plain array with keyword matching

Step 3: Declare the knowledge base in agent.yaml

agent.yaml sits in the project root. It is the Agent's configuration file and is deployed together with the code package. Declare the MCP server there and mount it on the Agent:

name: my-agent
model: deepseek-v4-pro
system: You are an assistant. Search the knowledge base before answering.

mcp_servers:
- type: url
name: kb
url: https://your-kb-service.example.com/mcp

tools:
- type: mcp_toolset
mcp_server_name: kb
default_config:
enabled: true
permission_policy:
type: always_allow

mcp_servers declares which MCP servers exist; tools declares which of them the Agent may use. The two must appear together — an entry in mcp_servers that is never mounted under tools will not be called.

If the project root does not have an agent.yaml yet, create one. The name, model, and system fields must all be present.

Field reference

FieldRequiredDescription
nameYesAgent name
modelYesModel ID; must already be enabled in the console
systemYesSystem prompt
mcp_servers[].typeYesOnly url is supported (remote HTTP MCP server); other values are ignored without an error
mcp_servers[].nameYesServer alias, referenced from tools
mcp_servers[].urlYesHTTP address of the MCP server
tools[].mcp_server_nameYesMatches mcp_servers[].name
tools[].default_config.enabledNoWhether the toolset is enabled; enabled by default
tools[].default_config.permission_policy.typeNoalways_allow calls automatically, always_ask prompts every time

Configuration sources and precedence

The runtime resolves configuration in a fixed order and stops at the first match:

  1. The AGENT_CONFIG / AGENT_CONFIG_B64 environment variables — a dynamic delivery channel intended for tooling; you do not need to set these by hand
  2. agent.yamlthe recommended approach; configuration travels with the code and can be version-controlled
  3. The AGENT_NAME / AGENT_MODEL / AGENT_SYSTEM environment variables — fallbacks for those three fields

Those same three environment variables also take precedence when present, overriding the matching fields from the layers above. The startup log prints only the final effective value.

Keep configuration in agent.yaml

If AGENT_MODEL is set on the function, changing model in agent.yaml has no effect — while name and system do change, which is easy to misread. Clearing these environment variables and managing everything from agent.yaml gives the most predictable behavior.

To view or change function environment variables, use Cloud Functions / Hosting → Function configuration → Environment variables in the console, or:

tcb agent update <agent-id> --env <KEY>=<VALUE>

Step 4: Deploy back to the cloud

agent.yaml only takes effect in the cloud when it is deployed together with the code package — the runtime reads /var/user/agent.yaml from the unpacked bundle. Creating it locally without deploying leaves the cloud unaware of it.

cd ./agent-code
tcb fn code update <function-name> --dir . -e <env-id>

The command asks for confirmation; choose Update with current config. While deploying, the function is in the Updating state and operations such as tcb fn code download are rejected.

Step 5: Verify

Trigger a cold start

Configuration is read when the process starts. After a deployment, existing instances may still be serving the previous configuration, so behavior will not change yet. Send one or two messages on the Integration & debugging tab to bring up a new instance.

Read the startup log

tcb logs search --query "function_name:\"<function-name>\" AND (\"[Agent]\" OR \"[Config]\")" \
--timeRange 30m -e <env-id>

A successful mount looks like this:

[Config] Loaded agent config from: /var/user/agent.yaml
[Agent] Name: my-agent
[Agent] Runtime: managed
[Agent] Model: deepseek-v4-pro
[Agent] Tools: 1 configured
[Agent] MCP Servers: 1 configured
[KernelAdapter] kernel Agent created (id=...)

Troubleshooting table:

SymptomMeaning
No Init Report ... Coldstart in the logThe request was served by an old instance and the configuration has not been reloaded; send another message or two
[Config] Loaded agent config from: /var/user/agent.yamlConfiguration was loaded from the yaml in the code package
[Config] No agent.yaml or AGENT_CONFIG found, using environment variablesNo yaml found, defaults are in use; check that the file was deployed with the code package
[Agent] MCP Servers: 0 configuredmcp_servers is missing from the yaml, or type is not url and the entry was skipped
[Agent] Tools: 0 configuredmcp_servers is declared but not mounted under tools

Send a message

On the Integration & debugging tab, ask a question that can only be answered from the knowledge base. The Agent calls mcp__kb__search first, then answers based on what it retrieved — the corresponding tool_call appears in the event stream.

Client-side integration is unchanged for Mini Programs, Web, and other clients — keep following the existing integration guide.

FAQ

I changed agent.yaml and deployed, but nothing changed

Check in order:

  1. Whether the log contains Init Report ... Coldstart. If not, an old instance is still serving; send another message or two to trigger a cold start
  2. Whether the [Config] line reads Loaded agent config from: /var/user/agent.yaml. If it reads No agent.yaml or AGENT_CONFIG found, the file did not make it into the code package — confirm it sits at the root of the deployed directory

The system prompt changed but the model did not

The AGENT_MODEL environment variable on the function takes precedence over model in agent.yaml. See Configuration sources and precedence.

Does an undeployed MCP server prevent the Agent from starting

No. MCP servers are connected on demand; startup only registers the configuration and performs no connectivity check. If the address is temporarily unreachable, the Agent still starts and ordinary conversation is unaffected — only the retrieval tool call itself fails. You can finish the configuration before deploying the retrieval service.

Which MCP server types are supported

Only type: url, a remote MCP server reachable over HTTP. Other types are ignored silently without an error, showing up as a lower-than-expected [Agent] MCP Servers count.

Can configuration be changed without redeploying the code

Changes to agent.yaml require redeploying the code package. The runtime also has an environment-variable-based dynamic delivery channel (AGENT_CONFIG) intended for the accompanying tooling; setting it by hand is not recommended.