indykite/skills

indykite-ciq-create-node

Author an IndyKite ContX IQ (CIQ) policy plus its Knowledge Query that creates a brand-new node in the IndyKite Graph (IKG), then run it via `POST /contx-iq/v1/execute`.

First seen May 19, 2026

Installation

$ npx skills add indykite/skills --skill indykite-ciq-create-node

Summary

  • Author an IndyKite ContX IQ (CIQ) policy plus its Knowledge Query that creates a brand-new node in the IndyKite Graph (IKG), then run it via `POST /contx-iq/v1/execute`.
  • Use when ingesting a new entity through CIQ - no relationship creation, no updates to existing nodes, no deletes.

Also in this package

Other skills from indykite/skills · top by installs.

npx skills add indykite/skills

Browse all from indykite/skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 4
License LICENSE
Default branch main
Open issues 1
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

LicenseApache-2.0
CompatibilityRequires curl, bash 4+, and jq. Network access to the regional IndyKite REST API (eu.api.indykite.com or us.api.indykite.com) is required at runtime.

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 15,500 B
  • docs SUMMARY.md 315 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 54 installs

SKILL.md

IndyKite ContX IQ - create a new node

Create a brand-new node in the IndyKite Graph (IKG) through a ContX IQ policy + Knowledge Query, run via POST /contx-iq/v1/execute. The policy declares an allowedupserts.nodes.nodetypes whitelist of node labels that may be created, and the Knowledge Query's upsertnodes array names the node, sets its externalid, and lists the properties to write. (CIQ writes use the same policy + Knowledge Query shape as reads.)

This skill covers exactly that - node creation only. Other write paths are deliberately out of scope:

  • Updating an existing node's properties uses allowedupserts.nodes.existingnodes and a Knowledge Query upsertnodes entry that references a variable from the policy's cypher (no externalid). Different field, different KQ shape.
  • Creating relationships uses allowedupserts.relationships.relationshiptypes ({type, sourcenodelabel, targetnodelabel} triples) and the Knowledge Query's upsert_relationships array.
  • Deletes use alloweddeletes and deletenodes / delete_relationships.

For reads, see [indykite-ciq-read](../indykite-ciq-read/SKILL.md).

When to use

Activate this skill when the user:

  • wants to create a new node in the IKG through CIQ (e.g. ingest a new Track, Document, Account, or other entity);
  • is authoring an _Application-subject "catalog write" policy + Knowledge Query - the typical pattern for ETL / system-side ingestion;
  • is parameterising the new node's externalid and properties from execute-time inputparams;
  • is debugging a 403 / 422 from a POST /contx-iq/v1/execute call that should have created a node but didn't.

Do not activate this skill when the user:

  • wants to read data from the IKG - use [indykite-ciq-read](../indykite-ciq-read/SKILL.md);
  • wants to update an existing node's properties - different policy field (existing_nodes) and KQ shape;
  • wants to create relationships between nodes - different policy field (relationshiptypes) and KQ array (upsertrelationships);
  • wants to delete anything - different policy field (allowed_deletes) and KQ array;
  • is using the Capture API (POST /capture/v1/nodes) or Terraform to ingest data instead of CIQ - those are separate ingestion paths.

Prerequisites

  • An IndyKite project, AppAgent, and AppAgent credentials (the AppAgent token goes into X-IK-ClientKey at execute time).
  • A Service Account token with Config API access, and the project's GID in PROJECT_GID - both used to create the policy and Knowledge Query.
  • The node label the new node will use (Track, Document, Customer, etc.) - already part of the project's data model.
  • For non-_Application subjects, the subject's node already in the IKG (CIQ doesn't create the subject; it authorizes against it).
  • A plan for external_id - the new node's stable identifier. Two choices the caller must make every time: hard-code it in the policy/KQ (rare), or supply it as a $param at execute time (common).

If any of these are missing, stop and tell the user - fixing them first is much cheaper than debugging a vague 403 or 422.

Steps

1. Pick the subject and Cypher anchor

Subject type - pick one. The schema is identical across both choices; only subject.type, the filter, and the execute-time auth differ:

Subject Use when Auth at execute time Filter convention
_Application System-side / ETL / catalog work; no user in the loop. X-IK-ClientKey only. subject.externalid = $appId (reserved).
Person / User The authenticated user is performing the operation themselves. X-IK-ClientKey + Authorization: Bearer <token>. subject.external_id = $token.sub.

A policy is restricted to a single subject type - if both should be allowed, write two policies. The runnable example below uses _Application (system-side catalog ingestion); a Person variant - for example, a user creating their own Playlist - differs only in subject.type, the filter, and the execute headers.

Cypher anchor - even a write-only policy needs a MATCH clause that anchors to the subject. The new node is not matched in cypher; it's declared in the Knowledge Query's upsert_nodes.

Working example (used throughout this skill):

System-side catalog ingestion: an Application creates a new Track node, supplying externalid, title, and loudness at execute time.

MATCH (subject:_Application)

That's the entire cypher - just enough to identify the subject. The Track does not appear here.

2. Author the policy with allowedupserts.nodes.nodetypes

Build the policy JSON with four blocks:

  • meta.policy_version - currently 1.0-ciq.
  • subject.type - _Application for the running example.
  • condition.cypher and condition.filter - anchor to the subject. For Application, filter on subject.externalid = $_appId (a reserved value auto-filled from the AppAgent at execute time).
  • allowedupserts.nodes.nodetypes - array of node labels the Knowledge Query may create as new nodes.

Omit allowedreads, alloweddeletes, and the other allowed_upserts sub-fields if this policy only creates nodes. Leaving them out is the supported way to forbid those operations.

A complete create-only policy for the running example: see [assets/policy-create-track.json](assets/policy-create-track.json).

Create it through the Config API:

# set the current project_id, and stringify only the `policy` field, before POSTing
jq --arg pid "$PROJECT_GID" '.project_id = $pid | .policy |= tojson' indykite-ciq-create-node/assets/policy-create-track.json \
  | curl -X POST "$API_URL/configs/v1/authorization-policies" \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $SERVICE_ACCOUNT_TOKEN" \
      -d @-

A 201 Created returns the policy's id (GID). Export it as POLICYID - the Knowledge Query create injects it into policyid.

For the full schema (operators, attribute conventions, why we omit existingnodes and allowedreads) see [references/policy-reference.md](references/policy-reference.md).

3. Create the Knowledge Query with upsert_nodes

The Knowledge Query references the policy and lists what to write. Each entry in upsert_nodes describes one node to create:

  • name - a distinct variable name not used in the policy's cypher. This is the variable other arrays (nodes, relationships) reference.
  • type - the node label. Must be in the policy's allowedupserts.nodes.nodetypes.
  • external_id - required for new nodes. Hardcode for one-off writes, or use $param (the common case) so the caller supplies it at execute time.
  • labels - optional array of extra labels attached alongside type. Chiefly used to create identity nodes - see the note below.
  • properties - array of {type, value, metadata?} items. The type (property name) must be hardcoded; the value may be hardcoded or $param.

Echo the new node back in the response by listing its variable name in the top-level nodes array.

Identity nodes. The Knowledge Query has no isidentity field - that flag belongs to the Capture API. In the IKG, identity status is carried by the DigitalTwin label; Capture's isidentity: true is shorthand for adding it at ingest. The CIQ equivalent is "labels": ["DigitalTwin"] on the upsertnodes entry. The label goes in labels only - the policy's nodetypes whitelist checks type, so DigitalTwin is never listed there. Create the node as an identity node whenever it must act as a 2.0-kbac subject: a non-identity subject makes every 2.0-kbac decision silently false (3.0-kbac does not require it). To confirm the label landed, run a 2.0-kbac evaluation with the new node as subject.

A complete Knowledge Query for the running example: see [assets/knowledge-query-create-track.json](assets/knowledge-query-create-track.json).

Create it through the Config API:

# set the current project_id and policy_id, and stringify only the `query` field, before POSTing
jq --arg pid "$PROJECT_GID" --arg polid "$POLICY_ID" '.project_id = $pid | .policy_id = $polid | .query |= tojson' indykite-ciq-create-node/assets/knowledge-query-create-track.json \
  | curl -X POST "$API_URL/configs/v1/knowledge-queries" \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $SERVICE_ACCOUNT_TOKEN" \
      -d @-

A 201 Created returns the Knowledge Query's id (GID) - what execute and the MCP ciq_execute tool will reference.

Schema details for every Knowledge Query field, including the protected property names you cannot set: [references/knowledge-query-reference.md](references/knowledge-query-reference.md).

4. Authenticate and execute

The execute endpoint is the same as for reads:

POST <API_URL>/contx-iq/v1/execute

Authentication for the running _Application-subject example:

  • X-IK-ClientKey: <AppAgent-credentials-token> - required.
  • Authorization: Bearer … - omit for Application subjects. The AppAgent itself authenticates the subject, and $appId is auto-filled from the application's external_id.

For Person-subject create flows, add Authorization: Bearer <user-access-token> and the policy's filter on subject.external_id = $token.sub will pin the cypher anchor to that user.

Request body:

{
  "id": "<knowledge_query_gid_or_name>",
  "input_params": {
    "track_external_id": "track-99",
    "track_title": "New Hot Track",
    "track_loudness": -7.5
  }
}

A runnable shell helper: [scripts/execute.sh](scripts/execute.sh).

Full execute reference (auth combinations, response shape, error codes): [references/execution-reference.md](references/execution-reference.md).

5. Verify the response and confirm the new node

A successful create execute returns the new node's projection:

{
  "data": [
    {
      "nodes": {
        "newTrack.external_id": "track-99",
        "newTrack.property.title": "New Hot Track",
        "newTrack.property.loudness": -7.5
      }
    }
  ]
}

If the response is not what you expected, walk this list before changing the policy or KQ:

  1. The label is whitelisted. The Knowledge Query's upsertnodes[].type must be in the policy's allowedupserts.nodes.node_types. Mismatch → 403.
  2. externalid is set. Required for new-node creation. If you're parameterising it ("$trackexternalid"), the caller must supply it in inputparams. Missing → 422 invalid_argument: missing or wrong input params.
  3. name doesn't collide with a cypher variable. The variable name in upsert_nodes[].name should be fresh - not a name that already appears in the policy's cypher. If it collides, the policy thinks you're updating an existing match instead of creating.
  4. Property names aren't in the protected set. service, createtime, externalid, id, type, updatetime cannot be set as properties - they're managed by the platform.
  5. The node didn't already exist. Re-running with the same external_id upserts (updates) instead of creating; the response will look similar but no new node is added.

For other failure modes (auth shape wrong, malformed JSON, subject filter mismatch) see [references/troubleshooting.md](references/troubleshooting.md).

Outcome

When this skill has been applied successfully:

  • A create-only CIQ policy exists in the project; it has a single subject.type, a Cypher pattern that anchors to the subject, optional partial filters, and an allowedupserts.nodes.nodetypes whitelist - no allowedreads, no alloweddeletes, no existing_nodes.
  • A Knowledge Query references that policy and lists exactly one new node in upsertnodes with a distinct name, the right type, an externalid, and the properties to set.
  • POST /contx-iq/v1/execute (or the MCP ciq_execute tool) returns the new node's projection on success.
  • A follow-up read query (e.g. via [indykite-ciq-read](../indykite-ciq-read/SKILL.md)) finds the new node in the IKG.

Files in this skill

  • [references/policy-reference.md](references/policy-reference.md) - write-focused policy schema, allowedupserts.nodes deep-dive (existing vs nodetypes), why other blocks are omitted.
  • [references/knowledge-query-reference.md](references/knowledge-query-reference.md) - upsert_nodes schema, properties + metadata, identity nodes via labels, protected property names, returning the new node.
  • [references/execution-reference.md](references/execution-reference.md) - POST /contx-iq/v1/execute for writes, auth combinations including Application reserved $appId, response shape.
  • [references/troubleshooting.md](references/troubleshooting.md) - 403 / 422 / duplicate external_id / missing properties patterns.
  • [assets/policy-create-track.json](assets/policy-create-track.json) - runnable create-only policy for the _Application → new Track example.
  • [assets/knowledge-query-create-track.json](assets/knowledge-query-create-track.json) - matching Knowledge Query.
  • [scripts/execute.sh](scripts/execute.sh) - Bash helper that posts to /contx-iq/v1/execute with the right headers.

Agent-specific notes

This skill uses generic markdown instructions and works across all agents listed in the [README](../README.md). The agent needs to be able to issue HTTP requests (curl, an HTTP client, or the IndyKite Terraform provider - see References). No Claude Code hooks, Cursor @-mentions, or Copilot workspace context are required.

References