Back to Docsgpt

Interacting with Agents via API

docs/content/Agents/api.mdx

0.17.110.7 KB
Original Source

import { Callout, Tabs } from 'nextra/components';

Interacting with Agents via API

DocsGPT Agents can be accessed programmatically through API endpoints. This page covers:

  • Non-streaming answers (/api/answer)
  • Streaming answers over SSE (/stream)
  • File/image attachments (/api/store_attachment + /api/task_status + /stream)

When you use an agent api_key, DocsGPT loads that agent's configuration automatically (prompt, tools, sources, default model). You usually only need to send question and api_key.

<Callout type="info"> Looking to connect an existing OpenAI-compatible client (opencode, aider, the OpenAI SDKs, etc.) to a DocsGPT Agent? Use the [OpenAI-Compatible Chat Completions API](/Agents/openai-compatible) — it speaks the standard chat completions protocol so no adapter code is required. </Callout>

Base URL

<Callout type="info"> For DocsGPT Cloud, use `https://gptcloud.arc53.com` as the base URL. </Callout>
  • Local: http://localhost:7091
  • Cloud: https://gptcloud.arc53.com

How Request Resolution Works

DocsGPT resolves your request in this order:

  1. If api_key is provided, DocsGPT loads the mapped agent and executes with that config.
  2. If agent_id is provided (typically with JWT auth), DocsGPT loads that agent if allowed.
  3. If neither is provided, DocsGPT uses request-level fields (prompt_id, active_docs, retriever, etc.).

Authentication:

  • Agent API-key flow: include api_key in JSON/form payload.
  • JWT flow (if auth enabled): include Authorization: Bearer <token>.

Endpoints

  • POST /api/answer (non-streaming)
  • POST /stream (SSE streaming)
  • POST /api/store_attachment (multipart upload)
  • GET /api/task_status?task_id=... (Celery task polling)

Request Parameters

Common request body fields:

FieldTypeRequiredApplies toNotes
questionstringYes/api/answer, /streamUser query.
api_keystringUsually/api/answer, /streamRecommended for agent API use. Loads agent config from key.
conversation_idstringNo/api/answer, /streamContinue an existing conversation.
historystring (JSON-encoded array)No/api/answer, /streamUsed for new conversations. Format: [{\"prompt\":\"...\",\"response\":\"...\"}].
model_idstringNo/api/answer, /streamOverride model for this request.
save_conversationbooleanNo/api/answer, /streamDefault true. If false, no conversation is persisted.
passthroughobjectNo/api/answer, /streamDynamic values injected into prompt templates.
prompt_idstringNo/api/answer, /streamIgnored when api_key already defines prompt.
active_docsstring or string[]No/api/answer, /streamOverrides active docs when not using key-owned source config.
retrieverstringNo/api/answer, /streamRetriever type (for example classic).
chunksnumberNo/api/answer, /streamRetrieval chunk count, default 2.
isNoneDocbooleanNo/api/answer, /streamSkip document retrieval.
agent_idstringNo/api/answer, /streamAlternative to api_key when using authenticated user context.

Streaming-only fields:

FieldTypeRequiredNotes
attachmentsstring[]NoList of attachment IDs from /api/task_status success result.
indexnumberNoUpdate an existing query index. If provided, conversation_id is required.

Non-Streaming API (/api/answer)

/api/answer waits for completion and returns one JSON response.

<Callout type="info"> `attachments` are currently handled through `/stream`. For file/image-attached queries, use the streaming endpoint. </Callout>

Response fields:

  • conversation_id
  • answer
  • sources
  • tool_calls
  • thought
  • Optional structured output metadata (structured, schema) when enabled

Examples

<Tabs items={['cURL', 'Python', 'JavaScript']}> <Tabs.Tab> bash curl -X POST http://localhost:7091/api/answer \ -H "Content-Type: application/json" \ -d '{"question":"your question here","api_key":"your_agent_api_key"}' </Tabs.Tab> <Tabs.Tab> ```python import requests

API_URL = "http://localhost:7091/api/answer"
API_KEY = "your_agent_api_key"
QUESTION = "your question here"

response = requests.post(
    API_URL,
    json={"question": QUESTION, "api_key": API_KEY}
)

if response.status_code == 200:
    print(response.json())
else:
    print(f"Error: {response.status_code}")
    print(response.text)
```

</Tabs.Tab> <Tabs.Tab> ```javascript const apiUrl = 'http://localhost:7091/api/answer'; const apiKey = 'your_agent_api_key'; const question = 'your question here';

async function getAnswer() {
try {
    const response = await fetch(apiUrl, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({ question, api_key: apiKey }),
    });

    if (!response.ok) {
    throw new Error(`HTTP error! Status: ${response.status}`);
    }

    const data = await response.json();
    console.log(data);
} catch (error) {
    console.error("Failed to fetch answer:", error);
}
}

getAnswer();
```

</Tabs.Tab> </Tabs>


Streaming API (/stream)

/stream returns a Server-Sent Events (SSE) stream so you can render output token-by-token.

SSE Event Types

Each data: frame is JSON with type:

  • answer: incremental answer chunk
  • source: source list/chunks
  • tool_calls: tool invocation results/metadata
  • thought: reasoning/thought chunk (agent dependent)
  • structured_answer: final structured payload (when schema mode is active)
  • id: final conversation ID
  • error: error message
  • end: stream is complete

Examples

<Tabs items={['cURL', 'Python', 'JavaScript']}> <Tabs.Tab> bash curl -X POST http://localhost:7091/stream \ -H "Content-Type: application/json" \ -H "Accept: text/event-stream" \ -d '{"question":"your question here","api_key":"your_agent_api_key"}' </Tabs.Tab> <Tabs.Tab> ```python import requests import json

API_URL = "http://localhost:7091/stream"
payload = {
    "question": "your question here",
    "api_key": "your_agent_api_key"
}

with requests.post(API_URL, json=payload, stream=True) as r:
    for line in r.iter_lines():
        if line:
            decoded_line = line.decode('utf-8')
            if decoded_line.startswith('data: '):
                try:
                    data = json.loads(decoded_line[6:])
                    print(data)
                except json.JSONDecodeError:
                    pass
```

</Tabs.Tab> <Tabs.Tab> ```javascript const apiUrl = 'http://localhost:7091/stream'; const apiKey = 'your_agent_api_key'; const question = 'your question here';

async function getStream() {
try {
    const response = await fetch(apiUrl, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'text/event-stream'
    },
    body: JSON.stringify({ question, api_key: apiKey }),
    });

    if (!response.ok) {
    throw new Error(`HTTP error! Status: ${response.status}`);
    }

    const reader = response.body.getReader();
    const decoder = new TextDecoder();

    while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    const chunk = decoder.decode(value, { stream: true });
    // Note: This parsing method assumes each chunk contains whole lines.
    // For a more robust production implementation, buffer the chunks
    // and process them line by line.
    const lines = chunk.split('\n');
    
    for (const line of lines) {
        if (line.startsWith('data: ')) {
        try {
            const data = JSON.parse(line.substring(6));
            console.log(data);
        } catch (e) {
            console.error("Failed to parse JSON from SSE event:", e);
        }
        }
    }
    }
} catch (error) {
    console.error("Failed to fetch stream:", error);
}
}

getStream();
```

</Tabs.Tab> </Tabs>


Attachments API (Including Images)

To attach an image (or other file) to a query:

  1. Upload file(s) to /api/store_attachment (multipart/form-data).
  2. Poll /api/task_status until status=SUCCESS.
  3. Read result.attachment_id from task result.
  4. Send that ID in /stream as attachments: ["..."].
<Callout type="warning"> Attachments are processed asynchronously. Do not call `/stream` with an attachment until its task has finished with `SUCCESS`. </Callout>

Step 1: Upload Attachment

POST /api/store_attachment

  • Content type: multipart/form-data
  • Form fields:
    • file (required, can be repeated for multi-file upload)
    • api_key (optional if JWT is present; useful for API-key-only flows)

Example upload (single image):

bash
curl -X POST http://localhost:7091/api/store_attachment \
  -F "file=@/absolute/path/to/image.png" \
  -F "api_key=your_agent_api_key"

Possible response (single-file upload):

json
{
  "success": true,
  "task_id": "34f1cb56-7c7f-4d5f-a973-4ea7e65f7a10",
  "message": "File uploaded successfully. Processing started."
}

Step 2: Poll Task Status

bash
curl "http://localhost:7091/api/task_status?task_id=34f1cb56-7c7f-4d5f-a973-4ea7e65f7a10"

When complete:

json
{
  "status": "SUCCESS",
  "result": {
    "attachment_id": "67b4f8f2618dc9f19384a9e1",
    "filename": "image.png",
    "mime_type": "image/png"
  }
}

Step 3: Attach to /stream Request

Use the attachment_id in attachments.

bash
curl -X POST http://localhost:7091/stream \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "question": "Describe this image",
    "api_key": "your_agent_api_key",
    "attachments": ["67b4f8f2618dc9f19384a9e1"]
  }'

Image/Attachment Behavior Notes

  • Typical image MIME types supported for native vision flows: image/png, image/jpeg, image/jpg, image/webp, image/gif.
  • If the selected model/provider does not support a file type natively, DocsGPT falls back to parsed text content.
  • For providers that support images but not native PDF file attachments, DocsGPT can convert PDF pages to images (synthetic PDF support).
  • Attachments are user-scoped. Upload and query must be done under the same user context (same API key owner or same JWT user).