Your own agent
Your own agents and scripts can use Workstate in two ways:
- Through MCP, as any other agent does. This gives you every tool: search, and reading and writing the ledger.
- Through the REST API, which the console uses. It searches, reads the ledger and lists repositories. It does not write to the ledger.
Both take the same API key, sent as Authorization: Bearer <key>. A full API reference is on the way Coming soon. This page covers the basics.
Through MCP
Use an MCP client library. The Model Context Protocol has official libraries for TypeScript, Python, C#, Go, Rust, Ruby, Java and other languages. See modelcontextprotocol.io/docs/sdk.
Set up the library's Streamable HTTP client with:
- the address:
https://mcp-uat.workstate.io/corpusfor search, orhttps://mcp-uat.workstate.io/ledgerfor the ledger - the
Authorization: Bearer <key>header - optionally, the
X-RAG-Namespaceheader, to choose a namespace, and theX-RAG-Agentheader, to name your agent in ledger entries
Then list the tools and call them by name. MCP tools lists every tool and its arguments. Each tool returns its result as text that holds JSON.
Try a single call
The servers are stateless, so a single HTTP request can call a tool. This is handy for testing. In your own software, use a library, which also handles the protocol's opening exchange.
bash
curl -s https://mcp-uat.workstate.io/corpus \
-H "Authorization: Bearer $RAG_API_KEY" \
-H "X-RAG-Namespace: ws-…" \
-H "Accept: application/json, text/event-stream" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_corpus","arguments":{"query":"where do we retry failed payments","top_k":5}}}'The answer is a JSON-RPC response. The search results are in result.content[0].text, as a string of JSON.
Through the REST API
The API's address is https://api-uat.workstate.io. Requests and responses are JSON.
Search
POST /v1/search searches one namespace.
| Field | Type | Required | Meaning |
|---|---|---|---|
query | string | Yes | What to find, in plain words. |
namespace | string | No | The namespace id. Without it, your oldest namespace. |
top_k | integer | No | How many results, from 1 to 100. The default is 8. |
repos | array of strings | No | Search only these repositories. An empty list returns no results. |
corpus | string | No | code, wiki or ledger. |
language | string | No | A language, such as python or markdown. |
path_prefix | string | No | Only files whose path starts with this, such as docs/. |
Two things differ from the search_corpus tool: repositories are always a list, named repos, and there is no rerank field.
bash
curl -s https://api-uat.workstate.io/v1/search \
-H "Authorization: Bearer $RAG_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "how do we retry failed payments", "namespace": "ws-…", "top_k": 5, "corpus": "code"}'Illustrative
This response is an example, shortened to one result. Real responses carry more fields, such as timings.
json
{
"query": "how do we retry failed payments",
"top_k": 5,
"reranked": true,
"results": [
{
"corpus": "code",
"repo": "payments-api",
"rel_path": "src/retry.ts",
"language": "typescript",
"start_line": 40,
"end_line": 72,
"text": "export async function retryPayment(payment: Payment) {",
"ann_score": 0.71,
"rerank_score": 0.93
}
]
}Cite a result by repo, rel_path and its lines, for example payments-api/src/retry.ts:40-72. See Search & citations.
Other endpoints
| Request | What it does |
|---|---|
POST /v1/ledger/search | Searches the ledger. Body: query, and optionally namespace, top_k, repos, type and status. |
POST /v1/ledger/list | Lists ledger topics a page at a time, most recently active first, with the total. Body, all optional: namespace, repos, type, status, created_after (an RFC 3339 time), limit (default 50, at most 200) and offset. |
GET /v1/ledger/{id}?namespace=… | Returns one topic with its full history. |
GET /v1/ledger/repos?namespace=… | Lists the projects that have ledger topics, and how many each has. |
GET /v1/repos?namespace=… | Lists the repositories in a namespace. Add &corpus=code, wiki or ledger to narrow it. |
To record in the ledger, use the MCP ledger server. An API key cannot create other keys: create keys in the console, on API keys.
Errors
Errors come back as JSON with an error field.
| Status | Example | What it means |
|---|---|---|
| 400 | {"error": "query must not be empty"} | The request is not valid. The message says why. |
| 401 | {"error": "unauthenticated", "detail": "invalid or revoked key"} | The key is missing, wrong or revoked. |
| 403 | {"error": "no grant for namespace \"ws-…\""} | Your key cannot reach that namespace. |
| 404 | {"error": "no such ledger topic"} | There is no such topic in the namespace. |
| 503 | {"error": "search is unavailable right now; try again in a few minutes"} | Search cannot answer right now. Try again later. |