mirror of
https://github.com/arc53/DocsGPT.git
synced 2025-11-29 08:33:20 +00:00
@@ -614,7 +614,7 @@ class Answer(Resource):
|
|||||||
try:
|
try:
|
||||||
question = data["question"]
|
question = data["question"]
|
||||||
history = limit_chat_history(
|
history = limit_chat_history(
|
||||||
json.loads(data.get("history", [])), gpt_model=gpt_model
|
json.loads(data.get("history", "[]")), gpt_model=gpt_model
|
||||||
)
|
)
|
||||||
conversation_id = data.get("conversation_id")
|
conversation_id = data.get("conversation_id")
|
||||||
prompt_id = data.get("prompt_id", "default")
|
prompt_id = data.get("prompt_id", "default")
|
||||||
|
|||||||
@@ -2,5 +2,13 @@
|
|||||||
"basics": {
|
"basics": {
|
||||||
"title": "🤖 Agent Basics",
|
"title": "🤖 Agent Basics",
|
||||||
"href": "/Agents/basics"
|
"href": "/Agents/basics"
|
||||||
|
},
|
||||||
|
"api": {
|
||||||
|
"title": "🔌 Agent API",
|
||||||
|
"href": "/Agents/api"
|
||||||
|
},
|
||||||
|
"webhooks": {
|
||||||
|
"title": "🪝 Agent Webhooks",
|
||||||
|
"href": "/Agents/webhooks"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
227
docs/pages/Agents/api.mdx
Normal file
227
docs/pages/Agents/api.mdx
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
---
|
||||||
|
title: Interacting with Agents via API
|
||||||
|
description: Learn how to programmatically interact with DocsGPT Agents using the streaming and non-streaming API endpoints.
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Callout, Tabs } from 'nextra/components';
|
||||||
|
|
||||||
|
# Interacting with Agents via API
|
||||||
|
|
||||||
|
DocsGPT Agents can be accessed programmatically through a dedicated API, allowing you to integrate their specialized capabilities into your own applications, scripts, and workflows. This guide covers the two primary methods for interacting with an agent: the streaming API for real-time responses and the non-streaming API for a single, consolidated answer.
|
||||||
|
|
||||||
|
When you use an API key generated for a specific agent, you do not need to pass `prompt`, `tools` etc. The agent's configuration (including its prompt, selected tools, and knowledge sources) is already associated with its unique API key.
|
||||||
|
|
||||||
|
### API Endpoints
|
||||||
|
|
||||||
|
- **Non-Streaming:** `http://localhost:7091/api/answer`
|
||||||
|
- **Streaming:** `http://localhost:7091/stream`
|
||||||
|
|
||||||
|
<Callout type="info">
|
||||||
|
For DocsGPT Cloud, use `https://gptcloud.arc53.com/` as the base URL.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
For more technical details, you can explore the API swagger documentation available for the cloud version or your local instance.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Non-Streaming API (`/api/answer`)
|
||||||
|
|
||||||
|
This is a standard synchronous endpoint. It waits for the agent to fully process the request and returns a single JSON object with the complete answer. This is the simplest method and is ideal for backend processes where a real-time feed is not required.
|
||||||
|
|
||||||
|
### Request
|
||||||
|
|
||||||
|
- **Endpoint:** `/api/answer`
|
||||||
|
- **Method:** `POST`
|
||||||
|
- **Payload:**
|
||||||
|
- `question` (string, required): The user's query or input for the agent.
|
||||||
|
- `api_key` (string, required): The unique API key for the agent you wish to interact with.
|
||||||
|
- `history` (string, optional): A JSON string representing the conversation history, e.g., `[{\"prompt\": \"first question\", \"answer\": \"first answer\"}]`.
|
||||||
|
|
||||||
|
### Response
|
||||||
|
|
||||||
|
A single JSON object containing:
|
||||||
|
- `answer`: The complete, final answer from the agent.
|
||||||
|
- `sources`: A list of sources the agent consulted.
|
||||||
|
- `conversation_id`: The unique ID for the interaction.
|
||||||
|
|
||||||
|
### 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`)
|
||||||
|
|
||||||
|
The `/stream` endpoint uses Server-Sent Events (SSE) to push data in real-time. This is ideal for applications where you want to display the response as it's being generated, such as in a live chatbot interface.
|
||||||
|
|
||||||
|
### Request
|
||||||
|
|
||||||
|
- **Endpoint:** `/stream`
|
||||||
|
- **Method:** `POST`
|
||||||
|
- **Payload:** Same as the non-streaming API.
|
||||||
|
|
||||||
|
### Response (SSE Stream)
|
||||||
|
|
||||||
|
The stream consists of multiple `data:` events, each containing a JSON object. Your client should listen for these events and process them based on their `type`.
|
||||||
|
|
||||||
|
**Event Types:**
|
||||||
|
- `answer`: A chunk of the agent's final answer.
|
||||||
|
- `source`: A document or source used by the agent.
|
||||||
|
- `thought`: A reasoning step from the agent (for ReAct agents).
|
||||||
|
- `id`: The unique `conversation_id` for the interaction.
|
||||||
|
- `error`: An error message.
|
||||||
|
- `end`: A final message indicating the stream has concluded.
|
||||||
|
|
||||||
|
### 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'
|
||||||
|
},
|
||||||
|
// Corrected line: 'apiKey' is changed to 'api_key'
|
||||||
|
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>
|
||||||
152
docs/pages/Agents/webhooks.mdx
Normal file
152
docs/pages/Agents/webhooks.mdx
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
---
|
||||||
|
title: Triggering Agents with Webhooks
|
||||||
|
description: Learn how to automate and integrate DocsGPT Agents using webhooks for asynchronous task execution.
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Callout, Tabs } from 'nextra/components';
|
||||||
|
|
||||||
|
# Triggering Agents with Webhooks
|
||||||
|
|
||||||
|
Agent Webhooks provide a powerful mechanism to trigger an agent's execution from external systems. Unlike the direct API which provides an immediate response, webhooks are designed for **asynchronous** operations. When you call a webhook, DocsGPT enqueues the agent's task for background processing and immediately returns a `task_id`. You then use this ID to poll for the result.
|
||||||
|
|
||||||
|
This workflow is ideal for integrating with services that expect a quick initial response (e.g., form submissions) or for triggering long-running tasks without tying up a client connection.
|
||||||
|
|
||||||
|
Each agent has its own unique webhook URL, which can be generated from the agent's edit page in the DocsGPT UI. This URL includes a secure token for authentication.
|
||||||
|
|
||||||
|
### API Endpoints
|
||||||
|
|
||||||
|
- **Webhook URL:** `http://localhost:7091/api/webhooks/agents/{AGENT_WEBHOOK_TOKEN}`
|
||||||
|
- **Task Status URL:** `http://localhost:7091/api/task_status`
|
||||||
|
|
||||||
|
<Callout type="info">
|
||||||
|
For DocsGPT Cloud, use `https://gptcloud.arc53.com/` as the base URL.
|
||||||
|
</Callout>
|
||||||
|
|
||||||
|
For more technical details, you can explore the API swagger documentation available for the cloud version or your local instance.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The Webhook Workflow
|
||||||
|
|
||||||
|
The process involves two main steps: triggering the task and polling for the result.
|
||||||
|
|
||||||
|
### Step 1: Trigger the Webhook
|
||||||
|
|
||||||
|
Send an HTTP `POST` request to the agent's unique webhook URL with the required payload. The structure of this payload should match what the agent's prompt and tools are designed to handle.
|
||||||
|
|
||||||
|
- **Method:** `POST`
|
||||||
|
- **Response:** A JSON object with a `task_id`. `{"task_id": "a1b2c3d4-e5f6-..."}`
|
||||||
|
|
||||||
|
<Tabs items={['cURL', 'Python', 'JavaScript']}>
|
||||||
|
<Tabs.Tab>
|
||||||
|
```bash
|
||||||
|
curl -X POST \
|
||||||
|
http://localhost:7091/api/webhooks/agents/your_webhook_token \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"question": "Your message to agent"}'
|
||||||
|
```
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab>
|
||||||
|
```python
|
||||||
|
import requests
|
||||||
|
|
||||||
|
WEBHOOK_URL = "http://localhost:7091/api/webhooks/agents/your_webhook_token"
|
||||||
|
payload = {"question": "Your message to agent"}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.post(WEBHOOK_URL, json=payload)
|
||||||
|
response.raise_for_status()
|
||||||
|
task_id = response.json().get("task_id")
|
||||||
|
print(f"Task successfully created with ID: {task_id}")
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
print(f"Error triggering webhook: {e}")
|
||||||
|
```
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab>
|
||||||
|
```javascript
|
||||||
|
const webhookUrl = 'http://localhost:7091/api/webhooks/agents/your_webhook_token';
|
||||||
|
const payload = { question: 'Your message to agent' };
|
||||||
|
|
||||||
|
async function triggerWebhook() {
|
||||||
|
try {
|
||||||
|
const response = await fetch(webhookUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(payload)
|
||||||
|
});
|
||||||
|
if (!response.ok) throw new Error(`HTTP error! ${response.status}`);
|
||||||
|
const data = await response.json();
|
||||||
|
console.log(`Task successfully created with ID: ${data.task_id}`);
|
||||||
|
return data.task_id;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error triggering webhook:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
triggerWebhook();
|
||||||
|
```
|
||||||
|
</Tabs.Tab>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
### Step 2: Poll for the Result
|
||||||
|
|
||||||
|
Once you have the `task_id`, periodically send a `GET` request to the `/api/task_status` endpoint until the task `status` is `SUCCESS` or `FAILURE`.
|
||||||
|
|
||||||
|
- **`status`**: The current state of the task (`PENDING`, `STARTED`, `SUCCESS`, `FAILURE`).
|
||||||
|
- **`result`**: The final output from the agent, available when the status is `SUCCESS` or `FAILURE`.
|
||||||
|
|
||||||
|
<Tabs items={['cURL', 'Python', 'JavaScript']}>
|
||||||
|
<Tabs.Tab>
|
||||||
|
```bash
|
||||||
|
# Replace the task_id with the one you received
|
||||||
|
curl http://localhost:7091/api/task_status?task_id=YOUR_TASK_ID
|
||||||
|
```
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab>
|
||||||
|
```python
|
||||||
|
import requests
|
||||||
|
import time
|
||||||
|
|
||||||
|
STATUS_URL = "http://localhost:7091/api/task_status"
|
||||||
|
task_id = "YOUR_TASK_ID"
|
||||||
|
|
||||||
|
while True:
|
||||||
|
response = requests.get(STATUS_URL, params={"task_id": task_id})
|
||||||
|
data = response.json()
|
||||||
|
status = data.get("status")
|
||||||
|
print(f"Current task status: {status}")
|
||||||
|
|
||||||
|
if status in ["SUCCESS", "FAILURE"]:
|
||||||
|
print("Final Result:")
|
||||||
|
print(data.get("result"))
|
||||||
|
break
|
||||||
|
|
||||||
|
time.sleep(2)
|
||||||
|
```
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab>
|
||||||
|
```javascript
|
||||||
|
const statusUrl = 'http://localhost:7091/api/task_status';
|
||||||
|
const taskId = 'YOUR_TASK_ID';
|
||||||
|
|
||||||
|
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
|
||||||
|
async function pollForResult() {
|
||||||
|
while (true) {
|
||||||
|
const response = await fetch(`${statusUrl}?task_id=${taskId}`);
|
||||||
|
const data = await response.json();
|
||||||
|
const status = data.status;
|
||||||
|
console.log(`Current task status: ${status}`);
|
||||||
|
|
||||||
|
if (status === 'SUCCESS' || status === 'FAILURE') {
|
||||||
|
console.log('Final Result:', data.result);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await sleep(2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pollForResult();
|
||||||
|
```
|
||||||
|
</Tabs.Tab>
|
||||||
|
</Tabs>
|
||||||
Reference in New Issue
Block a user