On this page

SDKs and APIs

Which identifier goes where

You are holding an id and you want to know which argument takes it. That is this page.

Wexa issues opaque ids and validates their format before a tool runs, so an id in the wrong argument is refused rather than quietly ignored. Two of them are worse than that: one has to be split before a few places will accept it, and one field name means two different things on the same object.

The short version

The id you holdWhere you got itWhat takes it
Agent idcreate-agent → agent_id; list-agents; the console URLagent_id on get-agent, update-agent, delete-agent, agent-versions, rollback-agent-version; agentflow_id on run-agent and create-schedule; target_id on list-triggers and set-triggers with target_type: "agent"; agent_id and after_agent_id on update-process-flow; start_from_agent_id on run-agent and run-process-flow
Agent id, left half onlythe agent id up to the dotagentflow_id on list-schedules; a trigger's agentflow_id inside update-agent; {agentflowId} in the chat completions path
Process flow idcreate-process-flow → flow._id; get-process-flow → _id; flow-versions → process_flow_idprocess_flow_id on seven tools, agentflow_id on four — the same id under two names
Schedule idcreate-schedule → schedule_idschedule_id on get-schedule, update-schedule, delete-schedule
Execution idrun-process-flow — see the caveat below; the pairing is documented by the gateway, not captured hereexecution_id on get-execution
Table idcreate-table → table_id; list-tables → tables[].table_idtable_id on ten of the twelve Data Table tools — every one except create-table and list-tables, which do not address an existing table; target_id on list-triggers and set-triggers with target_type: "table"
Column idget-table → columns[].column_idcolumn_id on edit-column and delete-column; the keys of row on update-table-row and of each rows entry on insert-table-rows, where a column_name is accepted too
Row idquery-table-rows → rows[]._id — not rows[].row_idrow_id on update-table-row; row_ids on delete-table-rows
Skill idlist-skills → skills[] — one entry per connector actionskill_ids on create-agent; skills inside agent on update-agent, which is the same list under a different name
Model idlist-models → available[].model_name or registry[].idmodel on create-agent and set-model
Version numberagent-versions / flow-versions → versions[] and live_version; promote-flow → versionversion on rollback-agent-version and rollback-flow-version; from_version and to_version on agent-versions — all integers, not ids
lifecycle_idevery responsenothing: it is the audit handle, not an argument

One object, three names

A process flow is addressed by three different spellings depending on where you are looking.

  • process_flow_id is the argument name on get-process-flow, update-process-flow, delete-process-flow, run-process-flow, flow-versions, promote-flow and rollback-flow-version — seven tools.
  • agentflow_id is the argument name on run-agent, run-process-flow, create-schedule and list-schedules — four tools. On run-process-flow, which takes both, the gateway's own schema calls agentflow_id an alias for process_flow_id.
  • _id is what the flow itself is keyed by in output: create-process-flow returns it as flow._id, get-process-flow returns it as _id, and promote-flow returns the same value as agentflowId — camel case, on that one field only.

They are one value. Nothing needs converting between them; only the name changes.

The compound agent id, and where to split it

create-agent does not return a plain id. It returns two ids joined by a dot:

{
  "lifecycle_id": "qlc_000105",
  "result": {
    "agent_id": "6ab17f077566f41b5c28e2ae.6ab17f074a4bd3812ca5e968"
  }
}

The part before the dot is the container the agent lives in; the part after it is the agent inside that container. Most tools take the whole thing, dot included, and split it themselves when they need the container:

  • every agent tool — get-agent, update-agent, delete-agent, agent-versions, rollback-agent-version
  • agentflow_id on run-agent and on create-schedule
  • target_id on list-triggers and set-triggers, for an agent target

Three places still need the left half today. Pass only the part before the dot:

  • agentflow_id on list-schedules, which refuses the whole id as malformed
  • a trigger's agentflow_id inside the agent you send to update-agent
  • {agentflowId} in the chat completions path
{
  "agentflow_id": "6ab17f077566f41b5c28e2ae"
}

The difference is a fault, not a rule: these three places will take the whole id once it is fixed.

Never build an agent id yourself. Take it from create-agent or list-agents.

Ids that are easy to confuse

Running an agent returns three ids, and only one of them polls

run-agent returns a large object. Three of its fields are identifiers, and they are easy to confuse:

  • execution_id — a UUID, and the only id get-execution accepts.
  • _id — the run record's own key, a 24-character hex string. get-execution answers a 404 for it.
  • agentflow_id — the flow that ran: the same id you passed in.

Verified against a live deployment. One run-agent call returned _id 6ab192bf7566f41b5c28e2e9 and execution_id 3c8cf2b5-612c-4700-be57-77b4d638ef37:

Passed to get-executionAnswer
_id404 — "Execution flow with ID 6ab192bf7566f41b5c28e2e9 not found"
execution_id200, returning the execution record

So an agent started with run-agent does have an execution record to poll. Read execution_id from the response and pass that. The argument description on get-execution says "Execution id returned by run-process-flow", which is true but incomplete: run-agent returns one too.

row_id means two different things

A Data Table row carries two fields whose names both suggest an identifier, and only one of them is one.

{
  "_id": "6ab179ea7566f41b5c28e260",
  "row_id": 1,
  "customer": "AcmeC",
  "amount": 120
}
  • _id is the row's identifier: an opaque string.
  • row_id is the row's position in the table: an integer, and not unique across tables.

The row_id argument on update-table-row and the row_ids argument on delete-table-rows both want _id, despite the name. Passing the integer is refused — and the refusal reports row_id as missing rather than as the wrong type, so read it as "not a string" when you know you sent one.

Column ids are sometimes names

get-table returns a column_id for every column, and for the columns the platform creates itself that id is the name — _id and row_id come back with column_id: "_id" and column_id: "row_id". Columns you add get an opaque id instead:

{ "column_id": "6ab17a6b3eecba4b44e58499", "column_name": "notes", "column_type": "String" }

Read the id from get-table rather than assuming either form. A row payload for update-table-row, or a rows entry for insert-table-rows, may be keyed by either column_id or column_name; a key that is neither is refused with the table's columns.

Ids you choose yourself

Two arguments look like ids and are not issued by the platform:

  • session_id on run-agent and run-process-flow is yours to pick. Reuse the same value across turns to get multi-turn memory and grouping; omit it for a one-shot run.
  • after_id on list-tables is a pagination cursor, and it has to be a table_id you saw on a previous page. A value that is not one is refused as a ValidationError, not as a 404.

See also How every tool call works and errors and retries.