Resources
Referencev1

Agent API reference

The same authenticated tool set, over two transports. New to this? Start with the BYO-agent guide for how to enable access and mint a token.

Base URL & authentication

All endpoints are served from the canonical host over HTTPS:

Base URLtext
https://www.diligio.co

Every request carries a Diligio agent token as a bearer credential. The token resolves to a specific user in a specific workspace; there are no separate API keys or client ids.

Required headerbash
Authorization: Bearer dgo_agent_...

One optional header is recorded in the audit log as a label and is never used for authorisation:

Optional headerbash
X-Agent-Identity: claude-opus-4-8/my-bot
Tokens act as a person
A token's effective permission is min(token level, the user's live role), re-resolved on every request. Both the workspace switch and the user's opt-in must be on or the call is refused. See Access levels.

REST endpoints

Three endpoints under /api/agent/v1. Tool calls return a uniform envelope: { "ok": true, "result": ... } on success, or { "error", "code" } with an HTTP status on failure.

Self-check

GET/api/agent/v1/me

Confirms the token works and reports the effective level plus the tools it grants. Good for a connection test.

Requestbash
curl -s https://www.diligio.co/api/agent/v1/me \
  -H "Authorization: Bearer $TOKEN"
200 responsejson
{
  "ok": true,
  "org_id": "8f3c...",
  "user_id": "a91b...",
  "role": "contributor",
  "level": "full",
  "agent": "claude-opus-4-8/my-bot",
  "tools": ["kb_search", "list_projects", "list_questions",
            "get_question", "write_answer", "set_question_status",
            "export_project"]
}

List tools

GET/api/agent/v1/tools

Returns the tools available to this token's level, each with its JSON-Schema input. Tools the level does not grant are omitted entirely.

200 response (truncated)json
{
  "tools": [
    {
      "name": "kb_search",
      "description": "Semantic-search the workspace knowledge base...",
      "input_schema": {
        "type": "object",
        "properties": {
          "query": { "type": "string", "description": "Natural-language query..." },
          "limit": { "type": "integer", "description": "Max results (1-10, default 5)." }
        },
        "required": ["query"],
        "additionalProperties": false
      }
    }
  ]
}

Call a tool

POST/api/agent/v1/tools/{tool}JSON body = the tool's arguments

The request body is the tool's arguments as a JSON object (send {} for tools that take none). The result is whatever the tool returns, wrapped in the success envelope.

Requestbash
curl -s -X POST https://www.diligio.co/api/agent/v1/tools/kb_search \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query":"data retention policy","limit":3}'
200 responsejson
{
  "ok": true,
  "result": [
    {
      "id": "0c2e...",
      "question": "What is your data retention policy?",
      "answer": "Client data is retained for the contract term plus 30 days...",
      "category": "Data Governance",
      "similarity": 0.81
    }
  ]
}

MCP (JSON-RPC)

POST/api/mcpStreamable HTTP, JSON-RPC 2.0

The MCP endpoint is https://www.diligio.co/api/mcp. It is a self-contained MCP server over Streamable HTTP: one JSON response per POST (no server-initiated SSE). The bearer header is the same as REST. See the guide for a Claude Desktop config.

Supported methods: initialize, ping, tools/list, tools/call, and the notifications/* acknowledgements. The default protocol version is 2025-06-18; the server identifies as { "name": "diligio", "version": "1.0.0" }.

initializejson
POST /api/mcp
Authorization: Bearer dgo_agent_...

{ "jsonrpc": "2.0", "id": 1, "method": "initialize",
  "params": { "protocolVersion": "2025-06-18" } }
tools/calljson
{ "jsonrpc": "2.0", "id": 2, "method": "tools/call",
  "params": {
    "name": "kb_search",
    "arguments": { "query": "encryption at rest" }
  } }

A tool result comes back as MCP content; tool-level failures are returned as content with isError: true (so the model can read the message) rather than a JSON-RPC error:

tools/call resultjson
{ "jsonrpc": "2.0", "id": 2, "result": {
    "content": [ { "type": "text", "text": "[ ... JSON ... ]" } ]
} }
A GET to /api/mcp returns 405 (there is no SSE stream). Auth failures during initialize return the REST-style { error, code } body with the matching HTTP status.

Caching & tokens

The single biggest lever on your input-token bill is your model provider's prompt cache: the system prompt, tool list and recent turns are reused across calls instead of re-priced in full. Provider caching is automatic once a stable prefix is sent, but it only fires when that prefix is byte-identical across calls. Diligio is built to make that true by construction, and to tell you exactly what would break it.

What Diligio guarantees

  • Deterministic tool order. tools/list returns tools in a fixed registry order on every call. The MCP spec (2026-07-28) calls this a SHOULD because it "improves LLM prompt cache hit rates"; we treat it as a hard rule and a build-time test fails if a reorder lands.
  • No per-call values in the listing. Tool names, descriptions and schemas never carry a timestamp, a count, a request id or your tenant name. A build-time scan rejects any of these.
  • Cache hints on every listing. MCP results carry ttlMs + cacheScope (private, because the tool set is capability-scoped to your token). REST listing reads (/me, /tools, /resources/read) carry an ETag and honour If-None-Match with a bodyless 304 when nothing changed.
  • A pinnable manifest. Read diligio://manifest/<protocol_version> (the version /me stamps) to get a content digest of your exact listing and the change-window policy. Compare the digest on every reconnect: if it changed, your prefix was going to bust anyway, so re-read /tools now.
Conditional REST re-list (zero tokens when unchanged)bash
curl -s https://www.diligio.co/api/agent/v1/tools \
  -H "Authorization: Bearer $TOKEN" \
  -H "If-None-Match: "$ETAG"  # from your previous response's ETag header"
# → HTTP 304 with no body when the listing is unchanged

Provider knobs you set

Provider caching must be requested at the breakpoints you choose. The exact field is provider-specific:

ProviderHow to cacheTTL
Anthropic (Claude)cache_control: { type: "ephemeral" } on the system / tools block you want cached5 min default, 1 hour with <code>ttl: "1h"</code> (1h billed at a higher write multiple)
OpenAI (GPT-4o/5)prompt_cache_key to bucket the session + prompt_cache_breakpoint to mark the prefix boundarysession-scoped, automatic on prefix match
Google (Gemini)implicit content cache, no manual breakpointautomatic on a stable prefix; see Gemini docs for the explicit-cache option
What invalidates the cache that YOU control

Beyond our deploys, three client-side changes silently kill your own cache hits. Keep them constant within a session:

  • tool_choice — changing it between calls invalidates the tool (and on some models, the system) cache.
  • The thinking config — toggling extended-thinking mode or changing budget_tokens rewrites the prefix.
  • The effort / reasoning setting — same effect; pick one and hold it.

The exact-copy rule also means JSON key order must be stable. Some SDKs randomise object key order when serialising tool_use blocks, which silently breaks the prefix hash. If your hit rate is unexpectedly low, serialise tool calls with stable key order.

The 1024-token floor

Most providers only cache prefixes above a minimum size (1,024 tokens on the Claude Sonnet/Opus family; up to 4,096 on some models). The always-on tool core for a full-access token clears this floor. A narrow read-only token (one tool, ~215 tokens) is genuinely below it and is served uncached: that is intentional, because padding a small slice to clear a cache floor would cost more than it saves.

Tool reference

Each Respond tool, its required level, input schema and an example. Of these, a read-only token reaches only kb_search. The Compliance set is summarised by domain below, and /api/agent/v1/tools returns every tool your own token grants with its schema.

Semantic search over the workspace knowledge base of previously answered questions. Use the returned answers as grounding; do not invent facts beyond them.

FieldTypeRequiredNotes
querystringyesNatural-language query. Max 2,000 characters.
limitintegernoResults to return, 1–10 (default 5).
Examplejson
// body
{ "query": "Do you support SSO?", "limit": 5 }

// result: array of hits
[ { "id": "...", "question": "...", "answer": "...",
    "category": "...", "similarity": 0.78 } ]

list_projects · full

Lists the DDQ / questionnaire projects visible to the user. No arguments.

Examplejson
// body
{}

// result
[ { "id": "...", "title": "Acme vendor DDQ", "client": "Acme",
    "status": "In Progress", "progress": 42,
    "created_at": "2026-06-01T10:00:00Z" } ]

list_questions · full

FieldTypeRequiredNotes
project_idstringyesFrom list_projects.
statusstringnoOptional status filter, e.g. "Drafting".
Examplejson
// body
{ "project_id": "...", "status": "Drafting" }

// result
[ { "id": "...", "number": 12, "category": "Security",
    "question": "...", "answer": null, "ai_draft": "...",
    "status": "Drafting", "confidence": 0.0,
    "answered_by_agent": false, "assignee_id": null,
    "due_date": null } ]

get_question · full

Fetch a single question in full detail.

Examplejson
// body
{ "question_id": "..." }

// result
{ "id": "...", "project_id": "...", "number": 12,
  "category": "Security", "question": "...", "answer": "...",
  "ai_draft": "...", "status": "SME Review", "confidence": 0.0,
  "answered_by_agent": true, "assignee_id": "...",
  "approver_id": "...", "due_date": null }

write_answer · full

Write (or overwrite) a question's answer with text the agent composed. The answer is flagged agent-authored and enters the human review workflow.

FieldTypeRequiredNotes
question_idstringyes
answerstringyesAnswer text. Max 100,000 characters.
Examplejson
// body
{ "question_id": "...", "answer": "Yes. Diligio supports SAML and OIDC SSO..." }

// result
{ "id": "..." }

set_question_status · full

Move a question through the review workflow. The same transition and role rules as a human in this role apply; finalising to Final is admin-only.

FieldTypeRequiredNotes
question_idstringyes
new_statusstringyesTarget status, e.g. "SME Review", "Pending human review", "Final".
Examplejson
// body
{ "question_id": "...", "new_status": "SME Review" }

// result
{ "id": "...", "status": "SME Review" }

export_project · full

Export a completed project to its source format and mark it Completed. A terminal action, reachable only by a full agent whose user is permitted to export.

Examplejson
// body
{ "project_id": "..." }

// result: the export descriptor (filename, format, location)

Compliance (GRC) tools

These appear only when the workspace runs Diligio Compliance and the token's user holds a GRC role. Reads need any GRC role; proposing needs a full token held by a grc_admin. Agents propose; a human certifies (tenants can opt in to delegated certification with a status allow-list and daily cap). The set is large, so it is self-documenting: call /api/agent/v1/tools with your token and every tool your token grants comes back with its input schema. The domains, at a glance:

DomainRepresentative toolsWrites
Worklist & recipesgrc_next_actions, grc_evidence_recipe, grc_list_skillsread-only
Posture & frameworksgrc_list_frameworks, grc_list_controls, grc_get_control, grc_list_gaps, grc_propose_status, grc_propose_many, grc_fill_mapped, grc_preview_certifyproposals (human-certified)
Evidencegrc_list_evidence, grc_add_evidence, grc_link_evidence, grc_verify_evidence_anchordirect, hash-anchorable
Registersgrc_create_risk / asset / policy / person / device / vendor / subprocessor, attestations, training, checklistsdirect planning writes
Monitoringgrc_list_connectors, grc_run_checks, grc_record_check_runs (push mode), grc_list_check_history, grc_control_healthverdicts, never posture
Reviews & auditsaccess reviews, internal audits, incidents, audit projects & PBC requests, re-attestationdirect + proposals
Trust & questionnairesTrust Center config, subprocessors, questionnaires, grc_autofill_questionnaire, grc_suggest_answerdrafts (human-approved)
Exportsgrc_export, grc_verify_exportread-only, digest-signed
grc_propose_status: examplejson
// body
{ "framework": "iso27001", "control_key": "A.8.15",
  "status": "implemented", "note": "Centralised logging via...",
  "evidence_ids": ["<evidence id>"] }

// result
{ "ok": true, "pending": "implemented" }   // awaits human certification
grc_record_check_runs: zero-custody push modejson
// Your runner executes the checks on YOUR infrastructure (credentials
// never reach Diligio) and pushes the verdicts against a credential-less
// connector row that acts as the identity anchor.
// body
{ "connector_id": "<connector id>", "runs": [
  { "check_key": "aws_rds_encryption", "status": "pass",
    "resource": "db-prod-1", "ran_at": "2026-07-12T09:30:00Z" }
] }

// result: runs land append-only, stamped source: "self_attested",
// with control evidence auto-captured for passing control-mapped checks.

Human-only by design (no tool exists): publishing the Trust Center, deciding trust-access requests, minting auditor share links, and connector credentials. The end-to-end setup, including the full zero-custody loop a prospect's agent can run, is in the Compliance agent quickstart.

Errors

REST errors return { "error": "<message>", "code": "<code>" } with the HTTP status below. In MCP, auth errors surface the same way during initialize; tool failures come back as isError content.

StatuscodeWhen
401missing_tokenNo bearer token on the request.
401invalid_tokenMalformed, unknown or revoked token.
401revoked_tokenToken was explicitly revoked.
401expired_tokenToken passed its expiry.
403agent_mode_disabledThe workspace switch is off.
403user_unavailableThe token&apos;s user is no longer active in the workspace.
403user_disabledThe user&apos;s per-user switch is off.
403forbiddenThe tool exceeds this token's level.
400invalid_inputMissing/invalid arguments, or a non-JSON body.
405method_not_allowedGET on the MCP endpoint (POST only).
500internal_errorUnexpected server error.

Limits

  • kb_search: query up to 2,000 characters; limit clamped to 1–10.
  • write_answer: answer up to 100,000 characters.
  • Tool calls (and MCP requests) run up to 60 seconds; long exports are designed to finish inside that window.
  • Tokens act through a short-lived user session that is refreshed transparently; you never manage it.