Skip to content

Team task properties

properties is one optional JSON object on a team task that your team fills with its own keys: scheduling hints, a ticket number from another system, a review checklist. Hadron stores it, returns it with the task and, when the team has a schema, checks it. Hadron never reads a key to decide who gets the task or who may do what; the meaning is entirely yours.

It is written through the agent task tools (MCP) and the GraphQL createAgentTask and updateAgentTask operations. The hadron CLI has no task-properties command: its --properties flag on node commands is a different, older field on nodes. This page covers behavior merged in hadron-server#2877 (merge e09a1653). The rule behind it, cor:agt:050:28, is decided for who writes the properties and where they live (on each task, nothing inherited). The bounds, the codes, the schema's location and the event's payload are proposed and may still change.

Not on production at the time of writing

This page is read from the merged server source, not from a live run on production. Production did not yet contain the change when the page was written (server 0.0.1439).

What it is

Fact Detail
Shape One JSON object. An array, string, number or boolean is refused.
Where it lives On each task. Nothing is inherited: a child task does not show its root's value, and there is no derived root field. Read the root task to see the root's value.
Size At most 16 KiB of canonical JSON (compact, keys sorted, UTF-8).
Depth At most 64 levels of nesting. Deeper is refused PROPERTIES_TOO_LARGE.
Meaning Opaque to the platform. Your team's keys, your team's rules.

Who may write it

Who May write properties?
The task's owner Yes
A worker the owner reports to Yes
The App's manager Yes
The task's assignee Yes. An assignee who has no other authority over the task may write properties only: a patch from them that names any other field refuses the whole patch TASK_NOT_OWNER. An assignee who is also the owner, above the owner, or an App manager keeps that authority and may edit the other fields too.
Anyone else No. updateAgentTask refuses TASK_NOT_OWNER.

Whoever can read the task reads its properties.

Writing it

You send Result
Nothing (omit the field) The value is unchanged.
An object It replaces the whole value. There is no merge.
null The value is cleared. A clear skips every check below.
The same object it already holds A no-op: no write and no event. It is still checked against the current bounds and schema first, so resubmitting the stored value can be refused after the schema changes.

On create, a creator who may not write it is not refused. The properties are written only if the creator is one of the task's writers for this new task: its owner, someone the owner reports to, an App manager, or the assignee named in the same call. For any other creator the task is created without them, with no error, and the value is not even checked. After a create, read the task back if the value matters.

An ended task refuses edits. updateAgentTask on a finished or cancelled task returns TASK_ENDED. A caller with no authority at all gets TASK_NOT_OWNER first.

Writing properties is not progress on the task and clears no wake.

The checks, in order

Each write is judged the same way on every surface.

Order Check Refusal
1 The value is a JSON object. PROPERTIES_NOT_AN_OBJECT
2 It nests at most 64 levels and its canonical JSON is at most 16 KiB. PROPERTIES_TOO_LARGE
3 It satisfies the team's schema, when one applies. PROPERTIES_SCHEMA_VIOLATION
3 The team has a schema node that cannot be used. PROPERTIES_SCHEMA_UNUSABLE

PROPERTIES_TOO_LARGE is also returned when the value is too large to validate against the team's schema (the schema's node count times the value's node count passes a work budget of 200,000). Send a smaller value.

The team's schema

A team may constrain properties by putting a JSON Schema in the Team Agent's system memory at the loc schema:task-properties.

  • The schema is JSON Schema draft-07. It is the node's data.
  • The server finds it through the Team Agent's base chain, nearest Agent first. An App cannot override it.
  • With no Team Agent, or no node at that loc, there is no schema and any object within the bounds is accepted.
  • The server reads the schema as the platform, so a writer who cannot read the Team Agent's memory is checked all the same. The violation message names the path in the writer's own value and the failing keyword, for example (root) fails "required", and does not echo the schema's text.

When the schema is unusable

A node that exists but cannot be used refuses every non-null properties write with PROPERTIES_SCHEMA_UNUSABLE until it is fixed. It is never treated as "no schema". A schema is unusable when it:

  • is not a JSON object, or does not compile as draft-07;
  • is asynchronous ($async);
  • uses $ref, $recursiveRef or $dynamicRef;
  • uses pattern or patternProperties (regular expressions are refused outright);
  • sets uniqueItems: true;
  • holds more than 500 schema values, leaves included, or nests more than 32 levels, or is larger than 64 KiB of canonical JSON.

A property that is merely named pattern is fine; only the keyword is refused. PROPERTIES_SCHEMA_UNUSABLE is also returned when more than one installed Agent carries a roles: branch, because the server cannot tell which Team Agent's schema applies.

Refusal codes

Code When
PROPERTIES_NOT_AN_OBJECT The value is not a JSON object (and not null).
PROPERTIES_TOO_LARGE Over 16 KiB, over 64 levels deep, or too large to validate against the team's schema.
PROPERTIES_SCHEMA_VIOLATION The value does not satisfy schema:task-properties.
PROPERTIES_SCHEMA_UNUSABLE The schema exists but cannot be used, or the team's Team Agent is ambiguous.
TASK_NOT_OWNER The caller is not a writer, or has only assignee authority and the patch names a field other than properties.
TASK_ENDED The task is finished or cancelled.

The change event

A change is recorded as a task.properties-changed event, on create (when a value was set) and on a change. The event is passive history: it never wakes anyone, suppresses a wake or counts as activity. Its payload is {from, to}, where each is null (no value) or {bytes, sha256}, the size and SHA-256 of the canonical JSON. It never carries the content, which may describe sensitive scheduling. Read events with hadron_team_events; the list is in MCP tools.

Where it appears

Surface Carries properties
GraphQL AgentTask.properties: JSON, and properties on CreateAgentTaskInput and UpdateAgentTaskInput.
MCP hadron_task_create and hadron_task_update take it; hadron_task_get shows it as a properties: line.
CLI No task-properties command yet (hadron-cli#1118 is the companion, not built).
Portal No portal surface yet (hadron-portal#1340).