Agentic AI Suite

POST /v1/graph/insert, /delete, and /update add, remove, and replace individual documents in the existing categories of a built knowledge graph. POST /v1/graph/recluster reorganizes the communities of a partition that has changed a lot. For when to use them, see Incremental Graph Updates. For a step-by-step guide, see the Quick Start. For how the divergence is measured, see Divergence and Reorganization.

The endpoints are relative to the path of the project’s AutoGraph service, https://<EXTERNAL_ENDPOINT>:8529/autograph/{service_id_postfix}. service_id_postfix is the end of the service ID, such as vyk1t for arangodb-autograph-vyk1t. The serviceUrl in the project metadata of GET /_platform/acp/v1/project_by_name/{database}/{project} ends with it, for example .../autograph/vyk1t/.

EndpointOperationPurposeCall
POST /v1/graph/insertAddAdd new documents to an existing categorySynchronous
POST /v1/graph/deleteRemoveRemove documents that are in an existing category, with all their graph data and their files in the File ManagerSynchronous
POST /v1/graph/updateReplaceReplace documents that are in an existing category with a new versionAsynchronous
POST /v1/graph/reclusterReorganizeRebuild the communities of a partition with the FullGraphRAG strategy that has changed a lotAsynchronous
POST /v1/orchestrate with file_idsKnowledge graph buildAdd the added and replaced documents to the knowledge graphAsynchronous
Note:

The /v1/graph/* endpoints work on one existing category, which you set in category. A category is the label you give a document when you upload it to the File Manager, the second part of its scope [project, category]. Files imported with the legacy module field use that label instead. The endpoints cannot create a category. To add one, build it, see When to use IGU.

Add documents

POST https://<EXTERNAL_ENDPOINT>:8529/autograph/:service_id_postfix/v1/graph/insert

Adds new documents to an existing category. The API calls this operation insert. The call is synchronous.

The corpus and the target category have to exist already. If the project has exactly one category, you can omit category. Otherwise, it is required.

Request

Every document is identified by its File Manager file_id. Adding takes no inline content, so upload the document with POST /_platform/filemanager/_db/{database}/rag-input first and pass the returned ID.

{
  "files": [
    {
      "doc_name": "new-contract.pdf",
      "file_id": "<file-manager-file-id>"
    }
  ],
  "category": "legal"
}

Parameters

ParameterTypeRequiredDescription
filesobject[]YesThe documents to add. The list cannot be empty, cannot contain duplicate doc_name or file_id values, and cannot have more than 100 files per request.
files[].doc_namestringYesThe file name of the document. It has to match the File Manager file name of file_id.
files[].file_idstringYesThe File Manager ID to get the document from. Every entry needs one. If any entry is missing it, the whole batch is rejected with 400 and a message that lists the offending doc_name values.
categorystringConditionalThe existing category to add the documents to. Required unless the project has exactly one category.

There is no citable_url request field. AutoGraph reads the citable URL from the custom_metadata of the File Manager file and validates it the same way a corpus build does, so it has to be an http or https URL with valid characters. Set it on the file when you upload it.

Response

{
  "results": [
    {
      "doc_name": "new-contract.pdf",
      "success": true,
      "cluster_key": "cluster_legal_0",
      "rag_partition_id": "legal_0_a"
    }
  ]
}
FieldMeaning
doc_nameThe document this result refers to.
successWhether the document has been added.
error_messageSet if this file failed. The other files of the batch can still succeed.
cluster_keyThe existing cluster that has been selected for the document. Can be empty if there is no suitable neighbor in a cluster.
rag_partition_idThe knowledge graph partition of the selected cluster. Can be empty if there is no strategy profile yet.
file_idThe File Manager ID of the added document. Use this value in the file_ids of the knowledge graph build.
Note:

The response does not include the divergence. At this point, it would be measured before the knowledge graph build has created the entities of the new documents. Read it from GET /v1/orchestrate/{orchestration_id} once the knowledge graph build has run. See Where to read the divergence.

Adding extracts the text, creates an embedding, stores the document, assigns the closest existing cluster, and adds the membership and similarity edges. It only changes the corpus graph. To add the document to the knowledge graph, start a knowledge graph build with its file_id. AutoGraph resolves the partition itself, so you do not pass one, see Identifying documents for the knowledge graph.

The build only processes a document that is in a cluster with a strategy. Check cluster_key and rag_partition_id in the response before you start it:

ResponseWhat it meansWhat to do
Both are setThe document is in a cluster with a strategy.Pass its file_id to the knowledge graph build.
cluster_key is set, rag_partition_id is emptyThe cluster has no strategy yet. The build skips the document.Run the RAG Strategizer for the category, then start the build.
Both are emptyNo existing cluster is similar enough. The build skips the document.Build the category again, see When to use IGU.

The build lists skipped documents in unmatched_file_ids. If it skips all of them, it returns 409, see Telling the three 409 responses apart.

Status CodeMeaning
200The request has been processed. Check the success of every entry in results.
400Empty or invalid batch, more than 100 files, a missing file_id on any entry, corpus not built, invalid category, duplicate names or IDs, file name mismatch, or the file could not be retrieved from the File Manager.
401Authentication failed.
403Access denied.
409Another operation is currently changing the corpus.
500Server error.
503A required dependency is temporarily unavailable.

HTTP example

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "files": [{
      "doc_name": "new-contract.pdf",
      "file_id": "<file-manager-file-id>"
    }],
    "category": "legal"
  }' \
  https://<EXTERNAL_ENDPOINT>:8529/autograph/{service_id_postfix}/v1/graph/insert

Remove documents

POST https://<EXTERNAL_ENDPOINT>:8529/autograph/:service_id_postfix/v1/graph/delete

Removes documents from an existing category. The API calls this operation delete. The call is synchronous and does the whole removal itself. It cleans up the knowledge graph first, then the corpus graph. No Importer worker is involved, and there is no background job to wait for. The response is the final result.

Once the deletion has committed, AutoGraph also deletes the files of the removed documents, with all their versions, from the File Manager. To use a document again, upload it again. If deleting a file from the File Manager fails, the removal still reports success, and the file stays in the File Manager.

Use File Manager IDs in file_ids if you can, as they are stable. Otherwise, provide doc_names, which are looked up in the requested category. You need to provide at least one of the two lists.

Request

{
  "file_ids": [
    "<file-manager-file-id-1>",
    "<file-manager-file-id-2>"
  ],
  "category": "legal"
}

By file name instead:

{
  "doc_names": ["old-contract.pdf"],
  "category": "legal"
}

Parameters

ParameterTypeRequiredDescription
file_idsstring[]ConditionalThe File Manager IDs of the documents to remove. Required unless you provide doc_names.
doc_namesstring[]ConditionalThe file names to look up in category. Required unless you provide file_ids.
categorystringConditionalThe existing category the documents are in. Required unless the project has exactly one category.
Note:

The batch is validated before anything is removed. If one of the documents is invalid, the request returns 400 and nothing is removed.

Note:

Removing has no replica setting, because it has no workers. AutoGraph removes the knowledge graph data itself, with AQL queries, as part of this request. There are no Importer jobs to start or to scale, unlike a knowledge graph build.

Response

{
  "results": [
    {
      "file_id": "<file-manager-file-id-1>",
      "status": "LAYER2_DELETE_STATUS_SUCCESS",
      "rag_partition_id": "legal_0_a",
      "cluster_key": "cluster_legal_0",
      "similarity_edges_removed": 8,
      "divergence_score": 0.31,
      "needs_reclustering": true
    }
  ],
  "affected_rag_partitions": ["legal_0_a"],
  "removed_rag_partitions": [],
  "layer3_results": [
    {
      "rag_partition_id": "legal_0_a",
      "status": "LAYER3_DELETE_STATUS_SUCCESS",
      "documents_removed": 1,
      "chunks_removed": 8,
      "entities_removed": 490,
      "communities_removed": 0,
      "semantic_units_removed": 0,
      "edges_removed": 0
    }
  ],
  "overall_status": "DELETE_OVERALL_STATUS_COMMITTED",
  "affected_cluster_ids": ["cluster_legal_0"],
  "removed_cluster_ids": [],
  "delete_id": "del_1711812345_a1b2c3d4"
}

The response reports the outcome of the complete deletion, knowledge graph included. There is no importerOrchestration entry to poll, because a standalone removal does not write one.

FieldMeaning
delete_idThe ID of this deletion, and the key of the concurrency lock it holds. Log it, so that you can correlate a 409 from a parallel call with the deletion that was holding the lock.
overall_statusHow the deletion as a whole ended, see the table below.
resultsThe corpus graph result of every file, with the cluster and partition it belonged to, the number of similarity edges that were removed, and the divergence of the partition. If you removed documents by doc_names, file_id holds the file name.
layer3_resultsThe knowledge graph result of the cleanup, per partition, with its status and the counts of what was removed. The counts are AutoGraph’s own AQL totals, not Importer figures.
affected_rag_partitions / affected_cluster_idsThe partitions and clusters the deletion touched.
removed_rag_partitions / removed_cluster_idsThe partitions and clusters that became empty and have been dropped.

overall_status covers both stages and tells you whether you can retry.

ValueMeaning
DELETE_OVERALL_STATUS_COMMITTEDThe deletion succeeded in both the knowledge graph and the corpus graph.
DELETE_OVERALL_STATUS_ROLLED_BACKSomething failed, and the state from before the call has been restored. The documents are still in the graph, and it is safe to retry the same batch.
DELETE_OVERALL_STATUS_FAILEDSomething failed, and the restore itself was incomplete. Do not retry right away. Inspect the corpus and the knowledge graph before you call again.

In field and status names, LAYER3 refers to the knowledge graph and LAYER2 to the corpus graph. The status of a layer3_results entry is one of LAYER3_DELETE_STATUS_SUCCESS, LAYER3_DELETE_STATUS_FAILED, LAYER3_DELETE_STATUS_NOT_ATTEMPTED, or LAYER3_DELETE_STATUS_UNSPECIFIED.

Note:

NOT_ATTEMPTED is a success case. It means there were no knowledge graph collections for the deletion to work on, so there was nothing to clean up. The corpus graph removal still goes ahead, and overall_status can still be DELETE_OVERALL_STATUS_COMMITTED. Treat it as “nothing to do”, not as an error.

Tip:

A failed deletion is rolled back. AutoGraph snapshots the knowledge graph data before it removes anything. If the knowledge graph cleanup fails, the snapshot is restored and the corpus graph does not change. If the corpus graph removal then fails, the knowledge graph snapshots are restored as well. A deletion that unwinds this way reports DELETE_OVERALL_STATUS_ROLLED_BACK, and the same batch is safe to send again. Only DELETE_OVERALL_STATUS_FAILED means the restore did not complete.

When the deletion commits, AutoGraph calculates the divergence of every affected partition again and adds divergence_score and needs_reclustering to the result of each file. The fields are only present if overall_status is DELETE_OVERALL_STATUS_COMMITTED. A deletion that is rolled back or fails reports no divergence.

The removed documents can be in other partitions than the ones a later knowledge graph build processes, so keep needs_reclustering from this response. See Where to read the divergence.

Status CodeMeaning
200The deletion has been processed. Check overall_status and the status of every entry in results.
400Missing or duplicate identifiers, a category that does not exist, a document that is not in the category, or a document in another category. Nothing is removed.
401Authentication failed.
403Access denied.
409Another operation is currently changing the corpus. The delete_id of the deletion that holds the lock lets you correlate the two calls.
500Server error.
503A required dependency is temporarily unavailable.

HTTP example

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "file_ids": ["<file-manager-file-id>"],
    "category": "legal"
  }' \
  https://<EXTERNAL_ENDPOINT>:8529/autograph/{service_id_postfix}/v1/graph/delete

Replace documents

POST https://<EXTERNAL_ENDPOINT>:8529/autograph/:service_id_postfix/v1/graph/update

Replaces documents in an existing category with a new version. The API calls this operation update. The call is asynchronous.

Every document has to be in the requested category already. A single invalid document makes the whole batch fail before anything is changed.

Request

As when adding, every document is identified by its File Manager file_id. Replacing takes no inline content. AutoGraph always reads the new version from the File Manager. Upload the new version with POST /_platform/filemanager/_db/{database}/rag-input and pass the returned ID.

{
  "files": [
    {
      "doc_name": "existing-contract.txt",
      "file_id": "<file-manager-file-id>"
    }
  ],
  "category": "legal"
}

Parameters

ParameterTypeRequiredDescription
filesobject[]YesThe documents to replace. The list cannot be empty and cannot contain duplicate doc_name or file_id values. Unlike adding, replacing has no per-request file cap.
files[].doc_namestringYesThe file name of the document to replace. It has to match the File Manager file name of file_id.
files[].file_idstringYesThe File Manager ID to get the new version from. Every entry needs one. If any entry is missing it, the whole batch is rejected with 400 and a message that lists the offending doc_name values.
categorystringConditionalThe existing category the documents are in. Required unless the project has exactly one category. If you omit it in a project with a single category, the doc_name values are looked up in that category before anything is changed.

POST /v1/graph/update still accepts the deprecated module field, which is only honored when category is empty. Send category. Insert and delete have no module field at all.

Immediate response

{
  "update_id": "update_1721840400_a1b2c3d4",
  "accepted": true,
  "message": "Update started",
  "results": []
}

accepted: true means that replacing has been validated and started, not that it is done. Poll the importerOrchestration entry in the metadata of your platform project, which GET /_platform/acp/v1/project_by_name/{database}/{project} returns, under projectMetadata.autographService.importerOrchestration. The progress is in its message field, as a JSON string. Replacing goes through the following phases. In their names, L3 stands for the knowledge graph and L12 for the corpus graph:

  1. DELETE_L3: AutoGraph removes the old knowledge graph data with AQL queries of its own. This is synchronous, and no Importer is involved.
  2. DELETE_L12: Removes the old document from the corpus graph.
  3. INSERT_L12: Inserts the new version into the corpus graph and assigns a cluster to it.
  4. DONE: Replacing has succeeded or failed.

Replacing uses the same logic as a standalone removal. It saves a snapshot of the knowledge graph data and removes that data before it changes the corpus graph.

The final message, parsed, looks like this:

{
  "phase": "DONE",
  "status": "completed",
  "summary": "Updated 1 file(s) in Layers 1-2; run orchestrate to re-import Layer 3",
  "files": [
    {
      "file": "existing-contract.txt",
      "result": "updated",
      "cluster": "cluster_legal_0",
      "previous_cluster": "cluster_legal_1",
      "partition": "legal_0_a",
      "file_id": "<file-manager-file-id>"
    }
  ]
}
Field in files[]Meaning
fileThe document this result refers to.
resultThe result for this file, for example updated.
cluster / previous_clusterThe cluster that is assigned to the new version, and the cluster the old version belonged to.
partitionThe knowledge graph partition of the new cluster.
file_idThe File Manager ID of the new version. Use it in the file_ids of the knowledge graph build, and to add the document again with insert if replacing left it removed.
errorPresent only if this file failed.

Only file and result are always present. The service adds every other key conditionally, so read them as absent rather than empty when the value does not apply.

Warning:

Wait for phase: "DONE", not for status: "completed". The entry is shared with knowledge graph builds and reorganizations. Right after you start replacing, it can still hold the plain-text message of the previous build, such as Orchestration completed: 11 succeeded, 0 failed, with status: "completed".

Warning:

Check the result of every file as well as the top-level status. A run can report status: "completed" while an individual entry of files[] has an error. Read the result and error of each file before you treat the replacement as done.

Note:

The status does not include the divergence either. As when adding, the new version only reaches the knowledge graph through a knowledge graph build, so a value here would be measured before the new entities exist. Read it from GET /v1/orchestrate/{orchestration_id} afterwards.

Replacing waits for the old knowledge graph data to be removed before it adds the new version, so that old and new knowledge graph data do not exist side by side. It is still not a database transaction.

Warning:

If removing the old version succeeds but adding the new one fails, the document stays removed. Fix the problem and add it again with POST /v1/graph/insert, using the file_id from the entry of that file.

After the documents have been replaced, start a knowledge graph build to import the new version into the knowledge graph.

Status CodeMeaning
200Replacing has been validated and started. Poll for the result.
400Empty or invalid batch, a missing file_id on any entry, a category that does not exist, or a document that is not in the category.
401Authentication failed.
403Access denied.
409Another operation is currently changing the corpus.
500Server error.
503A required dependency is temporarily unavailable.

HTTP example

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "files": [{
      "doc_name": "existing-contract.txt",
      "file_id": "<file-manager-file-id>"
    }],
    "category": "legal"
  }' \
  https://<EXTERNAL_ENDPOINT>:8529/autograph/{service_id_postfix}/v1/graph/update

Reorganize partitions

POST https://<EXTERNAL_ENDPOINT>:8529/autograph/:service_id_postfix/v1/graph/recluster

Rebuilds the communities of up to five partitions with the FullGraphRAG strategy from their current entities. The API calls this operation recluster. The call returns right away and reports whether each partition was taken up. This is not a queue position, see the response below. Reorganizing runs asynchronously, and only one partition is reorganized at a time.

Call this endpoint if needs_reclustering: true is reported for a partition and you decide to rebuild its communities, which is expensive. AutoGraph never reorganizes on its own. The flag is reported by GET /v1/orchestrate/{orchestration_id}, by a removal once it has committed, and by the rags profile of the partition. Adding and replacing do not report it. If a replaced document moves to another cluster, the partition it left is reported nowhere but in its rags profile. See Where to read the divergence.

Only partitions with the FullGraphRAG strategy have communities that can be rebuilt. A partition with the VectorRAG strategy has no Entities or Communities, so there is nothing to rebuild, and such a partition is never flagged.

The flag is set when the divergence_score is above the threshold, which is 0.25 and not configurable. For how the divergence is calculated, with examples, and how the values change over time, see Divergence and Reorganization.

Warning:

Plan reorganizing as a maintenance operation. It holds the single service-wide write lock for its entire run, which can take up to 3600 seconds, and blocks every corpus build and every addition, removal, and replacement until it is done. Partitions are reorganized one after another, so a request for several of them blocks changes for roughly the sum of their run times. Run it in a window where nothing else has to change the corpus.

Request

{
  "partition_ids": ["legal_0_a", "engineering_0_a"]
}
ParameterTypeRequiredDescription
partition_idsstring[]YesOne or more rag_partition_id values, for example from the response of an addition, removal, or replacement. At least one non-empty ID is required, and at most five. Duplicates are ignored.
Note:

Five partitions per request is a hard cap. A request that lists more than five partition_ids is rejected with 400, and nothing is reorganized. Split larger sets into several requests. They still run one at a time, so splitting does not make them faster.

Response

{
  "results": [
    {
      "rag_partition_id": "legal_0_a",
      "accepted": true
    },
    {
      "rag_partition_id": "engineering_0_a",
      "accepted": true
    }
  ]
}
FieldMeaning
results[].rag_partition_idThe partition this result refers to.
results[].acceptedtrue if the request for this partition was taken up, or if it has been merged into a reorganization that is already running for this partition. It does not mean the work is queued, see the warning below.
results[].error_messageSet if reorganizing could not be scheduled for this partition, for example because the ID is empty.
Warning:

accepted: true is not a queue position. Partitions are reorganized one at a time, and there is no queue. A partition that has to wait for the write lock makes about ten attempts, one second apart, to get it and then gives up. It stays flagged with needs_reclustering, so that you can start it again later. The response reports accepted: true for those partitions too, so it does not tell you whether they ran.

Read the result of each partition from its rags strategy profile, not from importerOrchestration. The importerOrchestration entry in your project metadata shows the status of the job that has the lock, not the result of each partition. A partition that gave up waiting for another reorganization does not appear there at all. A partition that gave up waiting for any other operation appears as failed. The rags node of the partition has the reliable result.

Field on the rags nodeAfter a successful reorganization
needs_reclusteringCleared to false
last_reclustered_atSet to the time of the run
divergence_scoreReset to 0, and a new baseline is taken

If needs_reclustering is still true and last_reclustered_at has not moved, the partition was not reorganized, whether it failed or never got the lock. Trigger it again. See Where the values are stored.

Status CodeMeaning
200The request has been processed. Check the accepted value of every entry in results.
400partition_ids is missing or empty, or it lists more than five partitions.
401Authentication failed.
403Access denied.
500Server error.

Notes:

  • If a partition is already being reorganized, a second request is merged into it and does not start another Importer job.
  • Reorganizing uses the same service-wide write lock as builds and as adding, removing, and replacing documents, so it cannot run at the same time as these operations.
  • A reorganization that fails or is skipped does not clear needs_reclustering. Start it again once the lock is free.
  • For a partition without entities, the job reports 0 communities over 0 entities and finishes successfully without changing anything. A completed job does not mean that anything was rebuilt. Check last_reclustered_at and the Communities of the partition.
  • To learn what the Importer does while it reorganizes and how long it takes, see Importer Incremental Updates.

HTTP example

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "partition_ids": ["legal_0_a"]
  }' \
  https://<EXTERNAL_ENDPOINT>:8529/autograph/{service_id_postfix}/v1/graph/recluster

Build the knowledge graph for changed documents

POST https://<EXTERNAL_ENDPOINT>:8529/autograph/:service_id_postfix/v1/orchestrate

Adding and replacing only change the corpus graph. To extract the entities and relationships of the new content and add them to the knowledge graph, call POST /v1/orchestrate with the file_ids of the added and replaced documents. Only those documents are processed, in the partitions that contain them. You do not name the partitions. AutoGraph finds them from the IDs.

Removing does not need this call. It removes the knowledge graph data itself.

Request

{
  "project": "my_project",
  "replicas": 1,
  "file_ids": ["<added-or-replaced-file-id>"]
}

Parameters

ParameterTypeRequiredDescription
projectstringYesThe platform project of the corpus.
file_idsstring[]Yes, for an incremental updateThe file_id values from the response of an addition or the status of a replacement. A non-empty list skips the filter that otherwise only builds partitions that are not in the knowledge graph yet, so a partition that is already built can take the changed documents.
replicasintegerNoNumber of Importer workers. 1 is enough for a handful of documents.
categoriesstring[]NoNarrows the IDs to these categories. Sending categories without file_ids does not work for an incremental update, see Identifying documents for the knowledge graph.

For the complete list of parameters, the response, the credential handling, and the three kinds of 409, see Trigger Orchestration.

Identifying documents for the knowledge graph

The build identifies documents by file_id only, not by doc_name. Adding and replacing both require a File Manager file_id for every document, so you pass the same IDs on to the build. IDs have the form rag-input-{base64url(db:path)} and refer to a File Manager path, which is why the project has to be built through the File Manager. Upload a document with POST /_platform/filemanager/_db/{database}/rag-input and pass the returned ID.

A non-empty file_ids is what keeps an already built partition eligible, because it bypasses the filter that otherwise only builds partitions that are not in the {project}_kg knowledge graph yet. Sending categories alone does not bypass that filter, so it skips exactly the partitions that your addition or replacement touched. If nothing else is stale, the request is rejected with a 409 and a Nothing to orchestrate message, see Telling the three 409 responses apart.

Response

The call returns 202 with an orchestration_id and runs in the background. IDs that matched no document are listed in unmatched_file_ids, which is only reported on this response.

{
  "orchestration_id": "orch_1711812345_a1b2c3d4",
  "success": true,
  "message": "Orchestration started",
  "unmatched_file_ids": []
}

Poll GET /v1/orchestrate/{orchestration_id} until status leaves running. Each entry of jobs has the divergence_score and needs_reclustering of its partition. jobs only lists the partitions that the build processed. The partitions of removed documents, and the partitions that replaced documents moved away from, are not in it. To see all of them, read the rags profiles, for example with GET /v1/rag-strategizer/strategy.

HTTP example

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "project": "my_project",
    "replicas": 1,
    "file_ids": ["<added-or-replaced-file-id>"]
  }' \
  https://<EXTERNAL_ENDPOINT>:8529/autograph/{service_id_postfix}/v1/orchestrate

For all steps in order, with example requests, see the Quick Start.