13#include <neograph/provider.h>
15#include <neograph/tool_set.h>
16#include <neograph/types.h>
53namespace neograph::graph {
88struct ChannelLifecyclePolicy {
89 ChannelRetentionPolicy retention = ChannelRetentionPolicy::Unbounded;
90 std::uint64_t retention_limit = 0;
91 ChannelPersistencePolicy persistence = ChannelPersistencePolicy::Checkpoint;
93 bool operator==(
const ChannelLifecyclePolicy&)
const =
default;
103using ReducerFn = std::function<json(
const json& current,
const json& incoming)>;
147inline ChannelWrite provider_messages_write(std::vector<sp::Message> messages,
149 json projection = json::array();
150 for (
const auto& message : messages) {
152 to_json(item, project_message(message));
153 projection.push_back(std::move(item));
155 return ChannelWrite{
"messages", std::move(projection), mode,
156 std::make_shared<const std::vector<sp::Message>>(std::move(messages))};
159inline ChannelWrite provider_messages_write(
const sp::runtime::Result& outcome,
161 if (!outcome)
throw std::invalid_argument(
"Provider returned no owned outcome");
162 const auto& messages = outcome_messages(*outcome);
163 json projection = json::array();
164 for (
const auto& message : messages) {
166 to_json(item, project_message(message));
167 projection.push_back(std::move(item));
169 return ChannelWrite{
"messages", std::move(projection), mode,
170 std::shared_ptr<const std::vector<sp::Message>>(outcome, &messages)};
205 : std::runtime_error(reason), reason_(reason) {}
212 : std::runtime_error(reason), reason_(reason),
213 value_(std::move(value)) {}
217 const std::string&
reason()
const {
return reason_; }
221 const json&
value()
const {
return value_; }
228 const std::string&
node()
const {
return node_; }
231 void set_node(std::string node) { node_ = std::move(node); }
271 std::exception_ptr cause)
272 : std::runtime_error(make_message(node_name, attempts, cause)),
273 node_name_(std::move(node_name)), attempts_(attempts),
274 cause_(std::move(cause)) {}
276 const std::string& node_name()
const noexcept {
return node_name_; }
277 int attempts()
const noexcept {
return attempts_; }
278 const std::exception_ptr& cause()
const noexcept {
return cause_; }
281 static std::string make_message(
const std::string& node_name,
int attempts,
282 const std::exception_ptr& cause) {
283 std::string detail =
"unknown exception";
285 if (cause) std::rethrow_exception(cause);
286 }
catch (
const std::exception& e) {
289 return "Node '" + node_name +
"' failed after "
290 + std::to_string(attempts) +
" attempt(s): " + detail;
293 std::string node_name_;
295 std::exception_ptr cause_;
384 bool routable =
false;
414NEOGRAPH_API
bool is_author_failure_code(std::string_view code) noexcept;
420 std::uint64_t ordinal = 0;
438 std::string public_message;
444 bool routable =
false;
468 explicit NodeFailureError(std::string code, std::string public_message = {},
469 std::optional<bool> retryable = std::nullopt)
470 :
NodeFailureError(what_of(code, public_message), code, public_message, retryable) {}
473 const std::string&
code() const noexcept {
return code_; }
474 const std::string& public_message() const noexcept {
return public_message_; }
475 std::optional<bool> retryable() const noexcept {
return retryable_; }
481 std::optional<bool> retryable)
482 : std::runtime_error(std::move(what)), code_(std::move(code)),
483 public_message_(std::move(public_message)), retryable_(retryable) {}
486 static std::string what_of(
const std::string& code,
const std::string& public_message) {
488 throw std::invalid_argument(
489 "NodeFailureError code must match [a-z][a-z0-9_]*(.[a-z0-9_]+)+ "
490 "and must not use the reserved NG. prefix");
491 return public_message.empty() ? code : code +
": " + public_message;
495 std::string public_message_;
496 std::optional<bool> retryable_;
516 :
NodeFailureError(what_of(code, public_message), checked(code), public_message,
520 static std::string checked(
const std::string& code) {
521 if (code !=
"NG.HookBlocked" && code !=
"NG.Interrupted")
522 throw std::invalid_argument(
523 "RemoteControlFailure code must be NG.HookBlocked or NG.Interrupted");
526 static std::string what_of(
const std::string& code,
const std::string& public_message) {
527 return public_message.empty() ? code : code +
": " + public_message;
546 : std::runtime_error(what_of(node, attempt, timeout, stopped)), node_(std::move(node)),
547 attempt_(attempt), timeout_(timeout), stopped_(stopped) {}
550 const std::string&
node() const noexcept {
return node_; }
552 int attempt() const noexcept {
return attempt_; }
553 std::chrono::milliseconds timeout() const noexcept {
return timeout_; }
555 bool stopped() const noexcept {
return stopped_; }
558 static std::string what_of(
const std::string& node,
int attempt,
559 std::chrono::milliseconds timeout,
bool stopped) {
560 auto text =
"Node '" + node +
"' attempt " + std::to_string(attempt + 1) +
561 " timed out after " + std::to_string(timeout.count()) +
" ms";
562 if (!stopped) text +=
" and did not stop by its stop deadline; its effects are uncertain";
568 std::chrono::milliseconds timeout_{0};
569 bool stopped_ =
true;
576NEOGRAPH_API std::optional<NodeFailure>
node_failure_of(
const std::exception_ptr& error);
642 std::string source_node;
704 return static_cast<StreamMode>(
static_cast<uint8_t
>(a) |
static_cast<uint8_t
>(b));
711 return static_cast<StreamMode>(
static_cast<uint8_t
>(a) &
static_cast<uint8_t
>(b));
718 return static_cast<uint8_t
>(flags & test) != 0;
738 std::map<std::string, std::string>
routes;
794 std::string node_name;
795 std::optional<int> retry_attempt;
801 std::string node_name;
802 std::optional<std::string> command_goto;
803 std::size_t send_count = 0;
809 std::string node_name;
815 std::string node_name;
827 std::optional<std::string> command_goto;
828 std::vector<std::string> next_nodes;
829 std::optional<int> step;
835 std::vector<Send> sends;
840 std::string node_name;
841 std::optional<std::string> phase;
842 std::optional<std::string> checkpoint_id;
848 std::string node_name;
888 if (!callback)
return {};
889 return [callback = std::move(callback)](
const GraphEvent& event) {
NEOGRAPH_API export/import macro for shared-library builds.
Cooperative cancel primitive shared between caller and engine.
Engine-owned registry of custom graph callables.
Thread-safe container for all graph state channels.
A node attempt ran past its attempt_timeout_ms (#364).
int attempt() const noexcept
The attempt that timed out: 0 for the first one.
bool stopped() const noexcept
The cancelled attempt stopped before its stop deadline.
const std::string & node() const noexcept
The node whose attempt timed out.
A node failure annotated by the executor with dispatch context.
Fail a node with an author code.
NodeFailureError(std::string what, std::string code, std::string public_message, std::optional< bool > retryable)
For bindings that translate a foreign error: what() keeps that error's text.
const std::string & code() const noexcept
The author code; empty when the failure carries none (NG.TaskFailed).
Exception thrown from inside a node to trigger a dynamic breakpoint.
NodeInterrupt(const std::string &reason, json value)
Construct a NodeInterrupt carrying a structured payload.
void set_node(std::string node)
Record the throwing node's name. Called by the executor.
const std::string & node() const
The node that threw this interrupt.
const std::string & reason() const
Get the interrupt reason.
NodeInterrupt(const std::string &reason)
Construct a NodeInterrupt with a reason message.
const json & value() const
Get the structured payload.
A run control signal a remote peer reported for one call.
RemoteControlFailure(const std::string &code, const std::string &public_message)
code is "NG.HookBlocked" or "NG.Interrupted"; anything else throws std::invalid_argument.
Marker for exceptions that are configuration or definition verdicts (#364).
std::function< void(const GraphEvent &)> GraphStreamCallback
Callback for receiving graph execution events.
constexpr const char * START_NODE
Special node name representing the graph entry point.
NodeFailureKind
Why the executor stopped trying a failed node.
@ Deadline
The backoff before the next attempt would cross the run's deadline (RunContext::deadline,...
@ Ceiling
The run-level retry ceiling (Program RunBudget::max_node_retries) was reached before a retry.
@ NonRetryable
The failure's class, the author's hint or the node's non_retryable codes rule out a retry.
@ VisitLimit
The node was activated once more than its max_visits; it did not run (code NG.VisitLimit,...
@ Exhausted
Retryable, but every allowed attempt failed.
std::function< std::string(const NodeFailure &failure)> FailureTextRedactor
Decides the free text a failure record may carry (#364).
GraphStreamCallback adapt_typed_stream(TypedGraphStreamCallback callback)
Adapt a typed callback to the existing GraphStreamCallback surface.
NEOGRAPH_API TypedGraphEvent to_typed_event(const GraphEvent &event)
Convert the stable GraphEvent wire shape to an owning typed event.
StreamMode operator|(StreamMode a, StreamMode b)
Bitwise OR for StreamMode flags.
ChannelRetentionPolicy
Retention policy applied after a channel reducer produces a value.
@ Unbounded
Keep the reducer result unchanged.
@ Bounded
Keep at most retention_limit newest array elements.
@ Latest
Keep the newest array element (as a one-element array).
bool has_mode(StreamMode flags, StreamMode test)
Check if a specific stream mode flag is set.
constexpr const char * END_NODE
Special node name representing the graph exit point.
StreamMode
Bitfield flags for selecting which events to stream during execution.
@ TOKENS
LLM_TOKEN events (streaming tokens).
@ UPDATES
Channel write deltas per node.
@ EVENTS
NODE_START, NODE_END, INTERRUPT, ERROR events.
@ VALUES
Full state snapshot after each super-step.
@ DEBUG
Internal debug info (retry attempts, routing decisions).
NEOGRAPH_API FailureVerdict classify_failure(const std::exception_ptr &error, const CancelToken *run_token=nullptr) noexcept
Classify any failure the way the node retry loop and every tool path do: the most severe class found ...
NodeFailureClass
What a node failure means for retry and for failure routing.
@ ConfigError
NG.ConfigError: configuration or misuse, including provider request, authentication and permission fa...
@ ProviderFailed
NG.ProviderFailed: a transient provider failure (transport, timeout, server, overloaded,...
@ BudgetExhausted
NG.BudgetExhausted: budget or quota exhaustion.
@ SafetyBlocked
NG.SafetyBlocked: a provider safety block.
@ Ordinary
NG.TaskFailed, NG.SubgraphFailed or an author code.
@ EffectCommitted
NG.EffectCommitted: the attempt committed a non-idempotent effect, so running the node again could re...
@ EffectUncertain
NG.EffectUncertain: an effect whose outcome is not known (ProviderOutcomeError, an unconfirmed Tool e...
@ LogicError
NG.LogicError: std::logic_error, which includes integrity checks.
@ HookBlocked
Run control: HookBoundaryBlocked. Stops the run as before.
@ Timeout
NG.Timeout: the attempt ran past its attempt_timeout_ms, was cancelled, and stopped (NodeAttemptTimeo...
constexpr const char * kAbortedCode
NG.Aborted: the code of a failure exit that declares none.
StreamMode operator&(StreamMode a, StreamMode b)
Bitwise AND for StreamMode flags.
std::function< json(const json ¤t, const json &incoming)> ReducerFn
Custom reducer function signature.
constexpr const char * DEFAULT_ROUTE
Reserved route key selected when an open/unspecified condition returns no exact match.
ReducerType
Strategy for merging values when writing to a channel.
@ OVERWRITE
Replace the current value entirely.
@ APPEND
Append to the current value (arrays are concatenated).
@ CUSTOM
Use a custom reducer function.
NEOGRAPH_API const NodeFailure * node_failure_of(const NodeExecutionError &error) noexcept
The record the executor attached to error, or null when the executor's retry loop did not throw error...
std::function< std::string(const GraphState &)> ConditionFn
Condition function signature for conditional edge routing.
NEOGRAPH_API bool is_author_failure_code(std::string_view code) noexcept
True for an author code: [a-z][a-z0-9_]*(\.
constexpr const char * kVisitLimitCode
NG.VisitLimit: the code of a node activated once more than its max_visits.
ChannelPersistencePolicy
Whether a channel value is part of serialized checkpoints.
@ Ephemeral
Omit value; checkpoint resume rejects written ephemeral state.
std::function< void(const TypedGraphEvent &)> TypedGraphStreamCallback
Callback for the additive typed event view.
Typed per-call controls translated into the selected SDK provider family.
Typed channel update event.
Output of a node: a write to a named channel.
json value
Value to write.
Mode mode
Default preserves the pre-#91 behavior.
std::shared_ptr< const std::vector< sp::Message > > native_messages
Authoritative ordered provider messages paired with this portable write.
Mode
What the write means for the channel's current value (issue #91).
@ Overwrite
Replace the channel's value outright, ignoring the reducer.
@ Reduce
Feed the value through the channel's reducer.
std::string channel
Target channel name.
A state channel that holds a reducer, lifecycle policy, and version.
ReducerType reducer_type
Merge strategy.
ChannelLifecyclePolicy lifecycle
Retention and persistence policy.
uint64_t version
Value of the state's single write counter (GraphState::global_version) at this channel's last write; ...
json value
Current channel value.
ReducerFn reducer
Custom reducer (when type == CUSTOM).
std::string name
Channel name.
Serialized snapshot of graph execution state at a single super-step.
Combined routing override + state update.
std::vector< ChannelWrite > updates
State updates to apply before routing.
std::string goto_node
Next node to execute (overrides edge routing).
A conditional edge with runtime routing based on state.
std::string from
Source node name.
std::string condition
Condition function name in ConditionRegistry.
std::map< std::string, std::string > routes
Mapping of condition result to destination node.
A static edge connecting two nodes.
std::string to
Destination node name.
std::string from
Source node name.
Typed execution error event. data preserves retry diagnostics.
The node failure classifier's verdict on any failure (see classify_failure).
std::exception_ptr signal
For the run control classes, the signal itself as found in the cause chain: the HookBoundaryBlocked,...
bool retryable
Sending the same request again may succeed: retryable_by_class, unless the node's retry loop already ...
std::string code
"NG.TaskFailed", "NG.HookBlocked", "NG.Cancelled", an author code, ...
std::string public_message
Text from typed safe sources only (NodeFailureError::public_message).
bool retryable_by_class
The failure's class and hints allow a retry, whether or not attempts were left: NodeFailure::retryabl...
An event emitted during graph execution for streaming.
json data
Event-specific data payload.
std::string node_name
Name of the node that generated this event.
Type
Event type enumeration.
@ NODE_START
A node began execution.
@ LLM_TOKEN
A token was received from the LLM.
@ CHANNEL_WRITE
A value was written to a channel.
@ INTERRUPT
Execution was interrupted (HITL).
@ ERROR
An error occurred during execution.
@ NODE_END
A node finished execution.
Typed HITL interrupt event. data remains available for custom metadata.
Dependency injection context passed to nodes during construction.
std::shared_ptr< Provider > provider
LLM provider for making completions.
json extra_config
Additional configuration (node-type specific).
std::shared_ptr< const GraphRegistry > registry
Construction-only registry snapshot inherited by built-in subgraphs.
std::string model
Model name override (empty = use provider default).
std::string provider_name
Identity metadata for an admitted Provider requirement.
std::vector< ChatTool > tool_definitions
Non-executable metadata for an admitted node's exact Tool requirements.
ProviderControls provider_controls
Explicit typed admission controls, including finite output cap.
ToolSet tools
Owned tool collection, shared cheaply across copies of this context, the compiled graph,...
std::string instructions
System prompt / instructions for the LLM.
Typed view of a node-end event. data preserves extension fields.
One mediated Tool effect of a node attempt, as seen by the run's ToolEffectBroker.
The classified outcome of a failed node.
std::string code
"NG.TaskFailed", "NG.SubgraphFailed", an author code, ...
int attempts
Attempts made, counting attempts made before a crash-resume.
bool retryable
The failure itself was retryable (its class and the author's hint), whether or not attempts were left...
std::vector< NodeFailureEffect > effects
Effects of the final attempt through the run's ToolEffectBroker, in the order they settled; empty wit...
std::string node
The node whose retry loop gave up.
Extended result returned by node execution.
std::vector< Send > sends
If non-empty, triggers dynamic fan-out.
std::optional< Command > command
If set, overrides edge-based routing.
std::vector< ChannelWrite > writes
Channel writes from this node.
NodeResult(std::vector< ChannelWrite > w)
Construct from plain channel writes (backward compatible).
Typed view of a node-start event. data preserves extension fields.
One NodeInterrupt of a paused super-step (#388).
std::string id
The paused invocation's stable task id, unique in its super-step: "s<step>:<node>" for a node of the ...
json value
{"type": "NodeInterrupt", "reason": ..., "value": ...}, the shape of RunResult::interrupt_value ("val...
std::string node
The node that raised it.
Escape hatch for malformed input or payload shapes added by future versions.
Retry policy for node execution with exponential backoff.
int initial_delay_ms
Delay before the first retry (milliseconds).
int max_delay_ms
Maximum delay cap (milliseconds).
float jitter_pct
Random jitter as a fraction of the computed delay, in [0, 1].
int max_retries
Maximum retry attempts. 0 = no retry.
float backoff_multiplier
Multiplier applied to delay after each retry.
Routing decision emitted for StreamMode::DEBUG.
Dynamic Send batch emitted for StreamMode::DEBUG.
Dynamic fan-out request (map-reduce pattern).
json input
Channel writes for that invocation.
std::string target_node
Node to dispatch.
Full serialized state emitted for StreamMode::VALUES.