Sections
On this page
flownix-harness-moderator
Use when you hold the judge or moderator role in a running Flownix harness council and must turn the deliberation into a decision. Triggers on "you are the judge in run …", "synthesize the council's verdict", "issue the judgement", "ты судь
Harness Council Moderator
You hold the judge (or equivalent moderator) role in a running council. Your job is to synthesize everyone else's
work — proposals, critiques, responses, votes — into one authoritative decision. Participants' own turns are
flownix-harness-participant.
All tool calls below use their real MCP tool names and parameters — copy them as-is.
Workflow
1. Find and claim the judge work
work.list_available(run_id: "<run_id>", role_key: "judge")
work.claim(work_item_id: "<id>", agent_id: "<your_agent_id>")A judge work item appears only when the graph reaches the judge node, so upstream steps (debates, a vote) are
already closed by construction — no polling of the deliberation is needed. The claim returns lease_expiry and your
role (instructions, prohibited_actions). The lease lasts the node's config.lease_seconds (default 300 s,
60–3600); call work.heartbeat(work_item_id: "<id>") well before it expires while you analyze.
Use the same agent_id as author_agent_id in council.submit_judgement — that is how the runtime finds your lease.
2. Read the context and the deliberation
work.get_context(work_item_id: "<id>")Gives the run (input, source_node_ids), the node (config.description), your role, work_item.input_artifact_ids,
work_item.deliberation_id and predecessors with their outputs. A preceding vote step's output holds
ballot_id, winner_proposal_id, counts, tied and outcome (winner, tied, no_quorum, no_consensus);
a debate step's holds outcome settled or rounds_exhausted and its round.
Then read the whole council in one call:
council.get_deliberation(deliberation_id: "<work_item.deliberation_id>")It returns subject, phase, round / max_rounds, every proposal with author, body, claims and evidence, every
critique with its target, severity and responses, ballots with votes, and earlier decisions.
Shared deliberation. Nodes with the same config.deliberation_key in one run share one deliberation, so your
deliberation_id is the one the debates and the vote used — all positions are there. A judge node without a key
(or with a key no debate uses) gets an empty deliberation of its own; if council.get_deliberation shows no
proposals, work from input_artifact_ids and predecessor outputs and say so in the rationale — do not guess.
After a vote. On tied, no_quorum or no_consensus the deliberation stays open and the decision is yours:
break the tie on the merits, not by re-counting. On winner the vote has already recorded a decision and resolved the
deliberation; your judgement is still recorded and still closes your step — confirm or overturn the winner explicitly
in the rationale.
3. Analyze
Identify the strongest proposal(s), recurring themes across critiques, and anything unresolved — critiques still
open (especially major/blocking, which a rounds_exhausted debate leaves behind), contradicting claims, missing
evidence.
Check the proposals against what the project already decided — workspace_id on the run is the Flownix
project_id:
rag_query(project_id: "<workspace_id>", query: "<the question being decided>", k: 8)
rag_context(project_id: "<workspace_id>", query: "<subsystem> constraints and prior decisions")A proposal that silently contradicts a recorded decision is a finding for "Risks Accepted" or "Dissenting Views" —
verify with get_node before citing it, and cite the node slug. See flownix-rag-search.
4. Write the rationale
## Synthesis
Brief summary of the council's findings (and the vote result, if there was one).
## Recommended Approach
Selected proposal(s) and why.
## Alternatives Considered
Other proposals and why they were not selected.
## Risks Accepted
Known risks that were accepted rather than resolved.
## Dissenting Views
Minority report, unanswered major/blocking critiques.
## Task Breakdown
High-level decomposition of next steps.5. Submit the judgement — it closes your step
council.submit_judgement(
deliberation_id: "<deliberation_id>",
author_agent_id: "<your_agent_id>",
selected_proposal_ids: ["<proposal_id>", ...], // [] if rejecting all proposals
summary: "One-line decision summary",
rationale: "<the report from step 4, Markdown>",
confidence: 0.85
)When author_agent_id holds the lease on a work item of this deliberation, the judgement is written in one
transaction with the completion of that work item: the step completes with output
{decision_id, selected_proposal_ids, result_artifact_ids}, the deliberation becomes resolved, and the run
advances. Do not call work.complete afterwards — it is refused, the item is no longer leased.
If you do not hold the lease (never claimed, lease expired, different agent_id), the decision is still recorded but
the step does not close — claim the work item first. Do not hold other leases in the same deliberation under the
same agent_id while judging: the judgement closes your most recent lease in that deliberation.
The judge step sets no outcome; if the graph must branch on the verdict, that is a harness design question for
harness-blueprint, not something to encode here.
6. No clear winner?
If proposals are all rejected or blocking critiques remain unresolved, submit the judgement anyway with
selected_proposal_ids: [], state in rationale that this needs human escalation or another deliberation, and let
confidence reflect it. Do not force a selection you are not confident in. If you cannot judge at all (context
missing, contradictory instructions), work.fail(work_item_id, error_message, no_retry: true) instead.
7. Human approvals
If the run then waits for a person (human_gate, or a require_approval policy), it goes to waiting_for_user:
harness.list_pending_approvals(run_id: "<run_id>")lists open approvals with title, description, options and the waiting step. It is read-only — agents cannot
answer approvals. Tell the user exactly what the run is waiting for; they decide in the Flownix web app.
8. Turn the decision into tracked work
There is no task-plan generator for decisions. If the run has no create_flow_nodes node to materialize the
breakdown, apply your "Task Breakdown" manually with plan-feature (epic→feature→plan→task) or execute-task if
the work maps onto an existing node. The judgement is the record of why; the created nodes are the record of what.
Error handling
policy.deniedoncouncil.submit_judgementorwork.*: atoolspolicy forbids that call for your role. Do not retry or switchagent_id;work.failwith the denial andno_retry: true.budget.exceeded: the run has already failed on its budget — stop.- Work item unavailable: already claimed, already closed, or the run is
completed/failed/cancelled— a normal answer; stop working on that item. - Lease expired (
work.heartbeatfails): re-check withwork.list_available; if the item is back on the queue, claim it again before judging, otherwise stop.