Skip to main content
The control API lets you mutate the state of running jobs and communicate directly with individual agents from Elixir. These are the same primitives the built-in CLI uses — pause, resume, and cancel operate at the job level, while send_message targets a specific agent within a job. All four functions route transparently across control and runtime nodes, so you do not need to manage cluster topology when calling them.

MirrorNeuron.pause/1

Pauses all agents in a running job. Paused agents stop processing new messages but retain their current state. Messages delivered while paused accumulate in each agent’s mailbox and are processed when the job resumes.
MirrorNeuron.pause(job_id)
job_id
String.t()
required
The unique job identifier returned by run_manifest/2.

Return value

Returns :ok on success, or {:error, reason} if the job cannot be found or the pause signal cannot be delivered.
:ok

Example

case MirrorNeuron.pause("prime_sweep_40_workers-abc123") do
  :ok ->
    IO.puts("Job paused successfully")

  {:error, reason} ->
    IO.puts("Pause failed: #{inspect(reason)}")
end
You can verify that all agents are paused by calling inspect_agents/1 and checking the "paused" field in each agent’s metadata. Agents that have already completed their work before the pause signal arrives will not be retroactively marked as paused.

MirrorNeuron.resume/1

Resumes a paused job. All agents that were paused begin processing their accumulated mailbox messages immediately after receiving the resume signal.
MirrorNeuron.resume(job_id)
job_id
String.t()
required
The unique job identifier of a currently paused job.

Return value

Returns :ok on success, or {:error, reason} if the job cannot be found or the resume signal cannot be delivered.
:ok

Example

:ok = MirrorNeuron.resume("prime_sweep_40_workers-abc123")
IO.puts("Job resumed")
pause/1 and resume/1 are useful for coordinating operator-driven interventions. Pause the job, use inspect_agents/1 to examine current agent state, then resume or cancel depending on what you find.

MirrorNeuron.cancel/1

Cancels a running or paused job. The runtime signals all agents to stop processing, transitions the job to the "cancelled" terminal state, and persists the final record in Redis.
MirrorNeuron.cancel(job_id)
job_id
String.t()
required
The unique job identifier.

Return value

Returns :ok on success, or {:error, reason} if the job cannot be found or is already in a terminal state.
:ok

Example

case MirrorNeuron.cancel("prime_sweep_40_workers-abc123") do
  :ok ->
    IO.puts("Job cancelled")

  {:error, reason} ->
    IO.puts("Cancel failed: #{inspect(reason)}")
end
Cancellation is permanent. Once a job enters the "cancelled" state it cannot be resumed. If you want to stop processing temporarily, use pause/1 instead.

MirrorNeuron.send_message/3

Delivers a message directly to a specific agent within a running job, bypassing the normal workflow routing rules. Use this for manual intervention, sensor-style external event injection, or testing agent behavior without running a full upstream pipeline.
MirrorNeuron.send_message(job_id, agent_id, message)
job_id
String.t()
required
The unique job identifier.
agent_id
String.t()
required
The identifier of the target agent within the job. Use inspect_agents/1 to enumerate available agent IDs.
message
map
required
The message payload to deliver. MirrorNeuron wraps this map in a runtime message envelope before dispatching it to the agent’s mailbox. The shape of the payload field is agent-type and template-specific.

Return value

Returns :ok when the message is successfully enqueued in the target agent’s mailbox, or {:error, reason} if the agent cannot be found or the job is not running.
:ok

Message payload shape

The message argument is a map you construct directly. A typical message for an executor or router agent looks like this:
{
  "type": "task",
  "payload": {
    "input": "check prime: 104729"
  }
}
For sensor-style injection or operator-driven workflows, you can also inject structured data:
{
  "type": "sensor_event",
  "payload": {
    "source": "external_monitor",
    "metric": "cpu_usage",
    "value": 0.92,
    "timestamp": "2026-03-28T11:00:00.000Z"
  }
}

Examples

Inject a task into a specific executor agent:
message = %{
  "type" => "task",
  "payload" => %{
    "input" => "check prime: 104729"
  }
}

case MirrorNeuron.send_message("prime_sweep_40_workers-abc123", "prime_worker_0001", message) do
  :ok ->
    IO.puts("Message delivered to prime_worker_0001")

  {:error, reason} ->
    IO.puts("Delivery failed: #{inspect(reason)}")
end
Inject an external event into a sensor agent:
event = %{
  "type" => "sensor_event",
  "payload" => %{
    "source" => "external_monitor",
    "metric" => "cpu_usage",
    "value" => 0.92,
    "timestamp" => DateTime.utc_now() |> DateTime.to_iso8601()
  }
}

:ok = MirrorNeuron.send_message("streaming_peak_demo-xyz789", "cpu_sensor", event)
Enumerate agents and target one by type:
{:ok, agents} = MirrorNeuron.inspect_agents("prime_sweep_40_workers-abc123")

dispatcher =
  Enum.find(agents, fn a -> a["agent_id"] == "dispatcher" end)

if dispatcher do
  :ok = MirrorNeuron.send_message(
    "prime_sweep_40_workers-abc123",
    dispatcher["agent_id"],
    %{"type" => "task", "payload" => %{"batch" => [97, 101, 103]}}
  )
end
send_message/3 delivers to the agent’s mailbox asynchronously. The agent processes the message according to its own concurrency model. Use inspect_agents/1 or events/1 after delivery to observe the effect.
Sending messages that do not match the agent’s expected input schema may cause the agent to error or produce unexpected output. Inspect the manifest and payload definitions in your job bundle before using send_message/3 in production workflows.