Create convo

Extracts entity state and relationship assertions from conversation turns and updates the graph.

POST /v1/graph/convo

Addresshttps://api.hanzo.ai/v1/graph/convo
MethodPOST
OperationgraphConvo
AuthAuthorization: Bearer $HANZO_API_KEY

Extracts entity state and relationship assertions from conversation turns and updates the graph.

First-person statements bind to the turn's speaker, second-person statements to its partner, and named subjects to their entity keys. Questions are skipped. Single-valued state updates (such as moving cities or changing roles) supersede prior values at the turn's timestamp, and explicit departures (such as leaving an employer) file a retraction ending the prior claim. Set dry_run to inspect what the turns state without writing.

Time: each turn's at (or the batch's at when omitted) is the valid instant of the assertions extracted from it, which an as_of read is bounded by; each becomes knowable at the write, which an as_known read is bounded by.

Request

9 fields, body application/json (required).

FieldInTypeRequiredDescription
atbodystringyesAt is the default valid instant for any turn that omits its own At, RFC 3339.
dry_runbodyboolean—DryRun when true returns the extracted assertions without writing them to the store.
sourcebodystringyesSource names the conversation these turns came from, such as chat/thread-42.
turnsbodygraph.graphTurn[]yesTurns is the ordered dialogue turns to read.
turns[].atbodystring—At is when this turn was spoken, RFC 3339.
turns[].idbodystring—ID is the turn's identifier within the conversation, appended to Source as #<id> in Evidence.
turns[].partnerbodystring—Partner is the entity key of the participant addressed in this turn.
turns[].speakerbodystringyesSpeaker is the entity key of the participant speaking this turn.
turns[].textbodystringyesText is what the speaker said.

Response

StatusBodyMeaning
200graph.graphConvoOutok
defaultproblem-detailsrefused

200 body — 15 fields.

FieldInTypeAlwaysDescription
assertionsbodygraph.graphFact[]—Assertions is the assertions extracted from the turns, in turn order.
assertions[].atbodystringyesAt is when the thing was so, RFC 3339.
assertions[].confidencebodynumber (double)—Confidence in [0,1].
assertions[].entitybodystringyesEntity is the thing being described, in the organization's own namespace.
assertions[].evidencebodystring—Evidence points at the record this claim came from, 512 bytes at most.
assertions[].namesbodyboolean—Names says the value is an entity.
assertions[].relationbodystringyesRelation is what is being asserted — depends, owner, same, title — and a key, folded as Entity is.
assertions[].seenbodystring—Seen is when this assertion became knowable, RFC 3339.
assertions[].sourcebodystringyesSource names who asserted.
assertions[].untilbodystring—Until is when the thing stopped being so, RFC 3339, and must follow At.
assertions[].valuebodystring—Value is what the relation points at.
duplicatebodyinteger (int64)—Duplicate is how many extracted assertions the store already held.
reasonsbodystring[]—Reasons names why each refused assertion was refused, in order.
recordedbodyinteger (int64)—Recorded is how many extracted assertions became new rows in the store.
refusedbodyinteger (int64)—Refused is how many extracted assertions were refused by admission or schema checks.

Failure carries the platform error shape — see Errors.

Examples

hanzo graph convo \
  --at <at> \
  --source <source> \
  --turns '[{"speaker":"<speaker>","text":"<text>"}]'
import { Configuration, GraphApi } from 'hanzoai';

const api = new GraphApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.graphConvo({ source: "<source>", at: "<at>", turns: [{"speaker":"<speaker>","text":"<text>"}] });
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import GraphApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = GraphApi(client).graph_convo(source="<source>", at="<at>", turns=[{"speaker":"<speaker>","text":"<text>"}])
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.GraphAPI.GraphConvo(context.Background()).Execute()
if err != nil {
	return err
}
use hanzo_client::apis::{configuration::Configuration, graph_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = graph_api::graph_convo(&cfg, Default::default()).await?;
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.GraphApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new GraphApi(client).graphConvo();

The method above is the one at the current release of the document. [email protected] (npm) and [email protected] (PyPI) were generated from an earlier release, where this operation carried a different id, so it spells the method differently — regenerating the clients is what makes the two agree. SDKs →

curl -X POST https://api.hanzo.ai/v1/graph/convo \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "source": "<source>",
       "at": "<at>",
       "turns": [
         {
           "speaker": "<speaker>",
           "text": "<text>"
         }
       ]
     }'

Tool graph, op graphConvo — POST the JSON-RPC envelope to https://api.hanzo.ai/v1/mcp.

curl -X POST https://api.hanzo.ai/v1/mcp \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "jsonrpc": "2.0",
       "id": 1,
       "method": "tools/call",
       "params": {
         "name": "graph",
         "arguments": {
           "op": "graphConvo",
           "input": {
             "source": "<source>",
             "at": "<at>",
             "turns": [
               {
                 "speaker": "<speaker>",
                 "text": "<text>"
               }
             ]
           }
         }
       }
     }'

Graph API · All Hanzo APIs · Interactive reference

Was this page useful?
Broken link or missing step? Drop it in #docs on Discord or open a PR.