/* NeMo Flow C API - Auto-generated by cbindgen. Do not edit. */

#ifndef NEMO_FLOW_H
#define NEMO_FLOW_H

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

/**
 * Status codes returned by all FFI functions.
 *
 * Every `extern "C"` function in this library returns an `NemoFlowStatus`.
 * On non-`Ok` returns, call [`nemo_flow_last_error`] on the same thread to
 * retrieve a human-readable error message.
 */
enum NemoFlowStatus {
  /**
   * Operation completed successfully.
   */
  NEMO_FLOW_STATUS_OK = 0,
  /**
   * A resource with the given name already exists.
   */
  NEMO_FLOW_STATUS_ALREADY_EXISTS = 1,
  /**
   * The requested resource was not found.
   */
  NEMO_FLOW_STATUS_NOT_FOUND = 2,
  /**
   * The scope stack is empty (no active scope).
   */
  NEMO_FLOW_STATUS_SCOPE_STACK_EMPTY = 3,
  /**
   * A guardrail rejected the operation.
   */
  NEMO_FLOW_STATUS_GUARDRAIL_REJECTED = 4,
  /**
   * An internal runtime error occurred.
   */
  NEMO_FLOW_STATUS_INTERNAL = 5,
  /**
   * A required pointer argument was null.
   */
  NEMO_FLOW_STATUS_NULL_POINTER = 6,
  /**
   * A JSON string argument could not be parsed.
   */
  NEMO_FLOW_STATUS_INVALID_JSON = 7,
  /**
   * A C string argument contained invalid UTF-8.
   */
  NEMO_FLOW_STATUS_INVALID_UTF8 = 8,
  /**
   * A function argument had an invalid value (e.g. malformed UUID).
   */
  NEMO_FLOW_STATUS_INVALID_ARG = 9,
};
typedef int32_t NemoFlowStatus;

/**
 * The type of scope in the agent execution hierarchy.
 */
enum NemoFlowScopeType {
  /**
   * Top-level agent scope.
   */
  NEMO_FLOW_SCOPE_TYPE_AGENT = 0,
  /**
   * Generic function scope.
   */
  NEMO_FLOW_SCOPE_TYPE_FUNCTION = 1,
  /**
   * Tool invocation scope.
   */
  NEMO_FLOW_SCOPE_TYPE_TOOL = 2,
  /**
   * LLM call scope.
   */
  NEMO_FLOW_SCOPE_TYPE_LLM = 3,
  /**
   * Retriever scope (e.g., RAG lookup).
   */
  NEMO_FLOW_SCOPE_TYPE_RETRIEVER = 4,
  /**
   * Embedder scope.
   */
  NEMO_FLOW_SCOPE_TYPE_EMBEDDER = 5,
  /**
   * Reranker scope.
   */
  NEMO_FLOW_SCOPE_TYPE_RERANKER = 6,
  /**
   * Guardrail evaluation scope.
   */
  NEMO_FLOW_SCOPE_TYPE_GUARDRAIL = 7,
  /**
   * Evaluator scope.
   */
  NEMO_FLOW_SCOPE_TYPE_EVALUATOR = 8,
  /**
   * User-defined custom scope.
   */
  NEMO_FLOW_SCOPE_TYPE_CUSTOM = 9,
  /**
   * Unknown or unspecified scope type.
   */
  NEMO_FLOW_SCOPE_TYPE_UNKNOWN = 10,
};
typedef int32_t NemoFlowScopeType;

/**
 * Opaque ATIF exporter handle.
 */
typedef struct FfiAtifExporter FfiAtifExporter;

/**
 * Opaque ATOF JSONL exporter handle.
 */
typedef struct FfiAtofExporter FfiAtofExporter;

/**
 * Opaque handle carrying both request and response codec trait objects.
 *
 * Created by `nemo_flow_openai_chat_codec_new` (and similar constructors).
 * Freed by `nemo_flow_codec_free`. The handle carries two `Arc`s pointing
 * to the same underlying codec instance: one for the `LlmCodec` trait and
 * one for the `LlmResponseCodec` trait.
 */
typedef struct FfiCodecHandle FfiCodecHandle;

/**
 * Opaque wrapper around a lifecycle event emitted by the runtime.
 */
typedef struct FfiEvent FfiEvent;

/**
 * Opaque handle representing an active LLM call.
 */
typedef struct FfiLLMHandle FfiLLMHandle;

/**
 * Opaque wrapper around an LLM request (headers, content).
 */
typedef struct FfiLLMRequest FfiLLMRequest;

/**
 * Opaque OpenInference subscriber handle.
 */
typedef struct FfiOpenInferenceSubscriber FfiOpenInferenceSubscriber;

/**
 * Opaque OpenTelemetry subscriber handle.
 */
typedef struct FfiOpenTelemetrySubscriber FfiOpenTelemetrySubscriber;

/**
 * Opaque plugin registration context.
 *
 * This wrapper contains a borrowed raw pointer to an
 * `nemo_flow::plugin::PluginRegistrationContext`, not an owned heap allocation.
 * It is only valid for the duration of the plugin registration callback that receives
 * it. C callers must not store the pointer, use it after the callback returns, or attempt to
 * free or drop it.
 *
 * There is intentionally no `nemo_flow_plugin_context_free` function because this FFI
 * wrapper does not own the underlying registration context.
 */
typedef struct FfiPluginContext FfiPluginContext;

/**
 * Opaque handle representing an active execution scope.
 */
typedef struct FfiScopeHandle FfiScopeHandle;

/**
 * Opaque handle to an isolated scope stack for per-request/per-task isolation.
 */
typedef struct FfiScopeStack FfiScopeStack;

/**
 * Opaque stream handle for consuming LLM streaming responses chunk by chunk.
 * Use `nemo_flow_stream_next` to poll and `nemo_flow_stream_free` to release.
 */
typedef struct FfiStream FfiStream;

/**
 * Opaque handle to a captured thread-local scope stack binding.
 */
typedef struct FfiThreadScopeStackBinding FfiThreadScopeStackBinding;

/**
 * Opaque handle representing an active tool call.
 */
typedef struct FfiToolHandle FfiToolHandle;

typedef struct Option_NemoFlowCollectorCb Option_NemoFlowCollectorCb;

typedef struct Option_NemoFlowFinalizerCb Option_NemoFlowFinalizerCb;

typedef struct Option_NemoFlowPluginValidateCb Option_NemoFlowPluginValidateCb;

/**
 * Callback for LLM execution (default callable). Receives a native JSON C string,
 * returns the response as a JSON C string.
 */
typedef char *(*NemoFlowLlmExecCb)(void *user_data, const char *native_json);

/**
 * Optional destructor for user data passed to callbacks.
 * Called when the runtime no longer needs the associated callback.
 */
typedef void (*NemoFlowFreeFn)(void *user_data);

/**
 * Nullable version of [`NemoFlowCodecDecodeCb`] for use as an optional
 * parameter in FFI execute functions. Pass null to indicate no codec.
 */
typedef char *(*NemoFlowCodecDecodeFn)(void *user_data, const struct FfiLLMRequest *request);

/**
 * Nullable version of [`NemoFlowCodecEncodeCb`] for use as an optional
 * parameter in FFI execute functions. Pass null to indicate no codec.
 */
typedef char *(*NemoFlowCodecEncodeFn)(void *user_data,
                                       const char *annotated_json,
                                       const struct FfiLLMRequest *original_request);

/**
 * Callback for LLM request sanitization. Receives an `FfiLLMRequest` and returns
 * a new (possibly modified) `FfiLLMRequest`. Return null to use defaults.
 */
typedef struct FfiLLMRequest *(*NemoFlowLlmRequestCb)(void *user_data,
                                                      const struct FfiLLMRequest *request);

/**
 * Generic JSON-to-JSON callback, used for LLM response sanitization and intercepts.
 * The returned string must be allocated with `malloc` or equivalent.
 */
typedef char *(*NemoFlowJsonCb)(void *user_data, const char *json);

/**
 * Callback for LLM conditional execution guardrails.
 * Returns NULL to allow execution, or an error message string to reject.
 */
typedef char *(*NemoFlowLlmConditionalCb)(void *user_data, const struct FfiLLMRequest *request);

/**
 * C callback type for LLM request intercepts with unified annotated-aware
 * signature. Receives the intercept name, the opaque `FfiLLMRequest`, and
 * optionally the annotated request as a JSON C string (null if no Codec
 * resolved). Writes transformed outputs to `out_request` and
 * `out_annotated_json`. Returns `NemoFlowStatus`.
 */
typedef NemoFlowStatus (*NemoFlowLlmRequestInterceptCb)(void *user_data,
                                                        const char *name,
                                                        const struct FfiLLMRequest *request,
                                                        const char *annotated_json,
                                                        struct FfiLLMRequest **out_request,
                                                        char **out_annotated_json);

/**
 * Runtime-provided "next" callback for LLM execution middleware chain.
 * Takes a native JSON C string, returns a response JSON C string.
 */
typedef char *(*NemoFlowLlmExecNextFn)(const char *native_json, void *next_ctx);

/**
 * Callback for LLM execution intercepts with middleware chain support.
 * Receives native JSON C string plus a `next` callback and its context.
 */
typedef char *(*NemoFlowLlmExecInterceptCb)(void *user_data,
                                            const char *native_json,
                                            NemoFlowLlmExecNextFn next_fn,
                                            void *next_ctx);

/**
 * Callback for event subscribers. Invoked on each lifecycle event emitted by
 * the runtime. The `FfiEvent` pointer is only valid for the duration of the call.
 */
typedef void (*NemoFlowEventSubscriberCb)(void *user_data, const struct FfiEvent *event);

/**
 * Callback for plugin registration.
 * Receives plugin config JSON and a plugin context pointer that is
 * only valid for the duration of the call.
 */
typedef NemoFlowStatus (*NemoFlowPluginRegisterCb)(void *user_data,
                                                   const char *plugin_config_json,
                                                   struct FfiPluginContext *ctx);

/**
 * Callback for tool request/response sanitization guardrails and intercepts.
 * Receives tool name and arguments as JSON, returns sanitized arguments as JSON.
 * The returned string must be allocated with `malloc` or equivalent.
 */
typedef char *(*NemoFlowToolSanitizeCb)(void *user_data, const char *name, const char *args_json);

/**
 * Callback for tool conditional execution guardrails.
 * Receives tool name and arguments as JSON.
 * Returns NULL to allow execution, or an error message string to reject.
 */
typedef char *(*NemoFlowToolConditionalCb)(void *user_data, const char *name, const char *args_json);

/**
 * Runtime-provided "next" callback for tool execution middleware chain.
 * Call this from an intercept to invoke the next layer (or original function).
 * `next_ctx` is an opaque pointer managed by the runtime.
 */
typedef char *(*NemoFlowToolExecNextFn)(const char *args_json, void *next_ctx);

/**
 * Callback for tool execution intercepts. Receives arguments as JSON plus
 * a `next` callback and its context. Call `next_fn(args, next_ctx)` to invoke
 * the next layer in the middleware chain, or return directly to short-circuit.
 */
typedef char *(*NemoFlowToolExecInterceptCb)(void *user_data,
                                             const char *args_json,
                                             NemoFlowToolExecNextFn next_fn,
                                             void *next_ctx);

/**
 * Callback for tool execution (default callable). Receives arguments as JSON,
 * returns result as JSON. The returned string must be allocated with `malloc`
 * or equivalent.
 */
typedef char *(*NemoFlowToolExecCb)(void *user_data, const char *args_json);

/**
 * Run the registered tool request intercept chain on the given arguments.
 *
 * This helper applies only the request-intercept middleware and does not emit
 * lifecycle events or execute the tool callback.
 *
 * # Parameters
 * - `name`: Tool name (null-terminated C string).
 * - `args_json`: Tool arguments as a JSON C string.
 * - `out`: On success, receives the transformed JSON string (caller must free
 *   with `nemo_flow_string_free`).
 *
 * # Returns
 * Returns [`NemoFlowStatus::Ok`] on success and writes the transformed JSON
 * string to `out`.
 *
 * # Safety
 * All pointers must be valid. `out` must be non-null.
 */
NemoFlowStatus nemo_flow_tool_request_intercepts(const char *name,
                                                 const char *args_json,
                                                 char **out);

/**
 * Run the registered tool conditional execution guardrail chain.
 *
 * Returns `NemoFlowStatus::Ok` if all guardrails pass, or
 * `NemoFlowStatus::GuardrailRejected` if blocked.
 *
 * # Parameters
 * - `name`: Tool name (null-terminated C string).
 * - `args_json`: Tool arguments as a JSON C string.
 *
 * # Returns
 * Returns [`NemoFlowStatus::Ok`] when execution is allowed and
 * [`NemoFlowStatus::GuardrailRejected`] when a guardrail blocks the call.
 *
 * # Safety
 * All pointers must be valid.
 */
NemoFlowStatus nemo_flow_tool_conditional_execution(const char *name, const char *args_json);

/**
 * Run the registered LLM request intercept chain on the given request.
 *
 * This helper applies only the request-intercept middleware and does not emit
 * lifecycle events or execute the provider callback.
 *
 * # Parameters
 * - `name`: Optional provider name as a null-terminated C string. Pass null to
 *   use an empty logical name.
 * - `native_json`: The request payload as a JSON C string representing an
 *   `LlmRequest` (`{"headers": {...}, "content": {...}}`).
 * - `out`: On success, receives the transformed JSON string (caller must free
 *   with `nemo_flow_string_free`). The output is a serialized `LlmRequest`.
 *
 * # Returns
 * Returns [`NemoFlowStatus::Ok`] on success and writes the transformed
 * serialized request to `out`.
 *
 * # Safety
 * All pointers must be valid. `out` must be non-null.
 */
NemoFlowStatus nemo_flow_llm_request_intercepts(const char *name,
                                                const char *native_json,
                                                char **out);

/**
 * Run the registered LLM conditional execution guardrail chain.
 *
 * Returns `NemoFlowStatus::Ok` if all guardrails pass, or
 * `NemoFlowStatus::GuardrailRejected` if blocked.
 *
 * # Parameters
 * - `native_json`: The request payload as a JSON C string representing an
 *   `LlmRequest` (`{"headers": {...}, "content": {...}}`).
 *
 * # Returns
 * Returns [`NemoFlowStatus::Ok`] when execution is allowed and
 * [`NemoFlowStatus::GuardrailRejected`] when a guardrail blocks the call.
 *
 * # Safety
 * All pointers must be valid.
 */
NemoFlowStatus nemo_flow_llm_conditional_execution(const char *native_json);

/**
 * Begin a manual LLM call lifecycle span.
 *
 * This emits an LLM Start event after applying sanitize-request guardrails to
 * the observability payload. Request and execution intercepts only run through
 * `nemo_flow_llm_call_execute`.
 *
 * # Parameters
 * - `name`: Null-terminated LLM provider name.
 * - `native_json`: The request payload as a JSON C string representing an
 *   `LlmRequest` (`{"headers": {...}, "content": {...}}`). The request
 *   becomes the start-event data after sanitize-request guardrails.
 * - `parent`: Optional parent scope handle, or null to use the current top of
 *   stack.
 * - `attributes`: Bitfield of LLM attributes.
 * - `data_json`: Optional null-terminated JSON string stored on the LLM
 *   handle, or null.
 * - `metadata_json`: Optional null-terminated JSON metadata string recorded
 *   on the start event, or null.
 * - `model_name`: Optional null-terminated LLM model identifier recorded in
 *   the LLM event category profile, or null.
 * - `timestamp_unix_micros`: Optional Unix microseconds timestamp for the
 *   handle start time and start event, or null to use the current UTC time.
 * - `out`: On success, receives a heap-allocated `FfiLLMHandle` that must be
 *   freed with `nemo_flow_llm_handle_free`.
 *
 * # Errors
 * Returns `InvalidJson` for invalid JSON inputs and `InvalidArg` when
 * `timestamp_unix_micros` is outside the supported timestamp range.
 *
 * # Safety
 * `name`, `native_json`, and `out` must be valid, non-null pointers. Optional
 * pointer arguments may be null; when non-null, they must be valid for reads
 * for the duration of the call.
 */
NemoFlowStatus nemo_flow_llm_call(const char *name,
                                  const char *native_json,
                                  const struct FfiScopeHandle *parent,
                                  uint32_t attributes,
                                  const char *data_json,
                                  const char *metadata_json,
                                  const char *model_name,
                                  const int64_t *timestamp_unix_micros,
                                  struct FfiLLMHandle **out);

/**
 * End a manual LLM call lifecycle span.
 *
 * This emits an LLM End event after applying sanitize-response guardrails to
 * the observability payload. Response intercepts only run through
 * `nemo_flow_llm_call_execute`.
 *
 * # Parameters
 * - `handle`: The LLM handle from `nemo_flow_llm_call`.
 * - `response_json`: LLM response as a null-terminated JSON C string. This
 *   response becomes the end-event data after sanitize-response guardrails
 *   unless it sanitizes to JSON null.
 * - `data_json`: Optional null-terminated JSON data used when the sanitized
 *   response is JSON null, or null.
 * - `metadata_json`: Optional null-terminated JSON metadata recorded on the
 *   end event, or null.
 * - `timestamp_unix_micros`: Optional Unix microseconds timestamp for the end
 *   event, or null to use the runtime default end timestamp.
 *
 * # Errors
 * Returns `InvalidJson` for invalid JSON inputs and `InvalidArg` when
 * `timestamp_unix_micros` is outside the supported timestamp range.
 *
 * # Safety
 * `handle` and `response_json` must be valid, non-null pointers. Optional
 * pointer arguments may be null; when non-null, they must be valid for reads
 * for the duration of the call.
 */
NemoFlowStatus nemo_flow_llm_call_end(const struct FfiLLMHandle *handle,
                                      const char *response_json,
                                      const char *data_json,
                                      const char *metadata_json,
                                      const int64_t *timestamp_unix_micros);

/**
 * Create a new OpenAI Chat Completions codec handle.
 *
 * The returned handle implements both request codec (decode/encode) and
 * response codec (decode_response). Free with `nemo_flow_codec_free`.
 *
 * # Safety
 * Caller must free the returned handle via `nemo_flow_codec_free`.
 */
struct FfiCodecHandle *nemo_flow_openai_chat_codec_new(void);

/**
 * Create a new OpenAI Responses API codec handle.
 *
 * The returned handle implements both request codec (decode/encode) and
 * response codec (decode_response). Free with `nemo_flow_codec_free`.
 *
 * # Safety
 * Caller must free the returned handle via `nemo_flow_codec_free`.
 */
struct FfiCodecHandle *nemo_flow_openai_responses_codec_new(void);

/**
 * Create a new Anthropic Messages API codec handle.
 *
 * The returned handle implements both request codec (decode/encode) and
 * response codec (decode_response). Free with `nemo_flow_codec_free`.
 *
 * # Safety
 * Caller must free the returned handle via `nemo_flow_codec_free`.
 */
struct FfiCodecHandle *nemo_flow_anthropic_messages_codec_new(void);

/**
 * Execute an LLM call end-to-end: run conditional-execution guardrails (on raw
 * request), then request intercepts, sanitize-request guardrails, execution
 * intercepts, the callback, and sanitize-response
 * guardrails. On rejection, only a standalone Mark event is emitted (no
 * Start/End pair) and `GuardrailRejected` is returned. Blocks the calling
 * thread until completion.
 *
 * # Parameters
 * - `name`: Null-terminated LLM provider name.
 * - `native_json`: The request payload as a JSON C string representing an
 *   `LlmRequest` (`{"headers": {...}, "content": {...}}`).
 * - `func`: C callback that performs the actual LLM call.
 * - `func_user_data`: Opaque pointer passed to `func`.
 * - `func_free`: Optional destructor for `func_user_data`.
 * - `parent`: Optional parent scope handle, or null.
 * - `attributes`: Bitfield of LLM attributes.
 * - `data_json`: Optional JSON data, or null.
 * - `metadata_json`: Optional JSON metadata, or null.
 * - `model_name`: Optional LLM model identifier, or null.
 * - `out`: On success, receives the response as a JSON C string. Caller must
 *   free with `nemo_flow_string_free`.
 *
 * # Safety
 * `name`, `native_json`, and `out` must be valid, non-null pointers.
 */
NemoFlowStatus nemo_flow_llm_call_execute(const char *name,
                                          const char *native_json,
                                          NemoFlowLlmExecCb func,
                                          void *func_user_data,
                                          NemoFlowFreeFn func_free,
                                          const struct FfiScopeHandle *parent,
                                          uint32_t attributes,
                                          const char *data_json,
                                          const char *metadata_json,
                                          const char *model_name,
                                          NemoFlowCodecDecodeFn codec_decode,
                                          NemoFlowCodecEncodeFn codec_encode,
                                          void *codec_user_data,
                                          NemoFlowFreeFn codec_free_fn,
                                          const struct FfiCodecHandle *response_codec,
                                          char **out);

/**
 * Execute a streaming LLM call end-to-end. Conditional-execution guardrails
 * run first on the raw request. Returns a stream handle that can be polled
 * with `nemo_flow_stream_next`. Blocks until the stream is set up.
 *
 * # Parameters
 * - `name`: Null-terminated LLM provider name.
 * - `native_json`: The request payload as a JSON C string representing an
 *   `LlmRequest` (`{"headers": {...}, "content": {...}}`).
 * - `func`: C callback that performs the actual LLM call.
 * - `func_user_data`: Opaque pointer passed to `func`.
 * - `func_free`: Optional destructor for `func_user_data`.
 * - `collector`: Callback invoked with each intercepted chunk as a JSON string.
 *   May be null, in which case chunks are not collected.
 * - `finalizer`: Callback invoked once when the stream is exhausted to produce
 *   the aggregated response as a JSON C string. May be null, in which case the
 *   finalizer returns `Json::Null`.
 * - `parent`: Optional parent scope handle, or null.
 * - `attributes`: Bitfield of LLM attributes.
 * - `data_json`: Optional JSON data, or null.
 * - `metadata_json`: Optional JSON metadata, or null.
 * - `model_name`: Optional LLM model identifier, or null.
 * - `out`: On success, receives a heap-allocated `FfiStream`.
 *
 * # Safety
 * `name`, `native_json`, and `out` must be valid, non-null pointers. `collector`
 * and `finalizer` may be null.
 */
NemoFlowStatus nemo_flow_llm_stream_call_execute(const char *name,
                                                 const char *native_json,
                                                 NemoFlowLlmExecCb func,
                                                 void *func_user_data,
                                                 NemoFlowFreeFn func_free,
                                                 struct Option_NemoFlowCollectorCb collector,
                                                 struct Option_NemoFlowFinalizerCb finalizer,
                                                 const struct FfiScopeHandle *parent,
                                                 uint32_t attributes,
                                                 const char *data_json,
                                                 const char *metadata_json,
                                                 const char *model_name,
                                                 NemoFlowCodecDecodeFn codec_decode,
                                                 NemoFlowCodecEncodeFn codec_encode,
                                                 void *codec_user_data,
                                                 NemoFlowFreeFn codec_free_fn,
                                                 const struct FfiCodecHandle *response_codec,
                                                 struct FfiStream **out);

/**
 * Poll the next chunk from a streaming LLM response. Blocks until a chunk is
 * available.
 *
 * # Returns
 * - `1`: A chunk was written to `*out_chunk`. Caller must free with
 *   `nemo_flow_string_free`.
 * - `0`: The stream is complete (no more chunks).
 * - `-1`: An error occurred. Call `nemo_flow_last_error` for details.
 *
 * # Safety
 * `stream` and `out_chunk` must be valid, non-null pointers.
 */
int32_t nemo_flow_stream_next(struct FfiStream *stream, char **out_chunk);

/**
 * Free a stream handle and release its resources.
 *
 * # Safety
 * `stream` must be a valid `FfiStream` pointer returned by
 * `nemo_flow_llm_stream_call_execute`, or null.
 */
void nemo_flow_stream_free(struct FfiStream *stream);

/**
 * Register an LLM request sanitization guardrail. The callback can modify or
 * replace the LLM request before it is sent.
 *
 * # Parameters
 * - `name`: Unique guardrail name.
 * - `priority`: Execution priority (lower runs first).
 * - `cb`: Request sanitize callback.
 * - `user_data`: Opaque pointer passed to `cb`.
 * - `free_fn`: Optional destructor for `user_data`.
 *
 * # Safety
 * `name` must be a valid C string. `cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_register_llm_sanitize_request_guardrail(const char *name,
                                                                 int32_t priority,
                                                                 NemoFlowLlmRequestCb cb,
                                                                 void *user_data,
                                                                 NemoFlowFreeFn free_fn);

/**
 * Deregister an LLM request sanitization guardrail by name.
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_deregister_llm_sanitize_request_guardrail(const char *name);

/**
 * Register an LLM response sanitization guardrail. The callback can inspect
 * and modify the LLM response after it is received.
 *
 * # Parameters
 * - `name`: Unique guardrail name.
 * - `priority`: Execution priority (lower runs first).
 * - `cb`: JSON-to-JSON callback that receives the response JSON and returns sanitized JSON.
 * - `user_data`: Opaque pointer passed to `cb`.
 * - `free_fn`: Optional destructor for `user_data`.
 *
 * # Safety
 * `name` must be a valid C string. `cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_register_llm_sanitize_response_guardrail(const char *name,
                                                                  int32_t priority,
                                                                  NemoFlowJsonCb cb,
                                                                  void *user_data,
                                                                  NemoFlowFreeFn free_fn);

/**
 * Deregister an LLM response sanitization guardrail by name.
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_deregister_llm_sanitize_response_guardrail(const char *name);

/**
 * Register an LLM conditional execution guardrail. The callback decides
 * whether an LLM call should proceed.
 *
 * # Parameters
 * - `name`: Unique guardrail name.
 * - `priority`: Execution priority (lower runs first).
 * - `cb`: Conditional callback. Returns null to allow, or error message to reject.
 * - `user_data`: Opaque pointer passed to `cb`.
 * - `free_fn`: Optional destructor for `user_data`.
 *
 * The callback is fallible. To signal an internal callback failure instead of
 * allow/reject, call [`crate::error::nemo_flow_set_last_error_message`] from C
 * and return null.
 *
 * # Safety
 * `name` must be a valid C string. `cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_register_llm_conditional_execution_guardrail(const char *name,
                                                                      int32_t priority,
                                                                      NemoFlowLlmConditionalCb cb,
                                                                      void *user_data,
                                                                      NemoFlowFreeFn free_fn);

/**
 * Deregister an LLM conditional execution guardrail by name.
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_deregister_llm_conditional_execution_guardrail(const char *name);

/**
 * Register an LLM request intercept. The callback can transform the
 * `LlmRequest` before it reaches the LLM provider.
 *
 * # Parameters
 * - `name`: Unique intercept name.
 * - `priority`: Execution priority (lower runs first).
 * - `break_chain`: If true, stop processing further intercepts after this one.
 * - `cb`: LLM request transform callback (receives/returns `FfiLLMRequest`).
 * - `user_data`: Opaque pointer passed to `cb`.
 * - `free_fn`: Optional destructor for `user_data`.
 *
 * The callback is fallible. To signal failure, call
 * [`crate::error::nemo_flow_set_last_error_message`] from C and return null.
 *
 * # Safety
 * `name` must be a valid C string. `cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_register_llm_request_intercept(const char *name,
                                                        int32_t priority,
                                                        bool break_chain,
                                                        NemoFlowLlmRequestInterceptCb cb,
                                                        void *user_data,
                                                        NemoFlowFreeFn free_fn);

/**
 * Deregister an LLM request intercept by name.
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_deregister_llm_request_intercept(const char *name);

/**
 * Register an LLM execution intercept following the middleware chain pattern.
 * The callback receives `(request, next_fn, next_ctx)` — call
 * `next_fn(request, next_ctx)` to invoke the next intercept or the original
 * LLM call, or skip calling it to short-circuit.
 *
 * # Parameters
 * - `name`: Unique intercept name.
 * - `priority`: Execution priority (lower runs first).
 * - `exec_cb`: Middleware callback receiving request and a next function.
 * - `exec_user_data`: Opaque pointer for the execution callback.
 * - `exec_free`: Optional destructor for `exec_user_data`.
 *
 * # Safety
 * `name` must be a valid C string. Callback pointers must be valid.
 */
NemoFlowStatus nemo_flow_register_llm_execution_intercept(const char *name,
                                                          int32_t priority,
                                                          NemoFlowLlmExecInterceptCb exec_cb,
                                                          void *exec_user_data,
                                                          NemoFlowFreeFn exec_free);

/**
 * Deregister an LLM execution intercept by name.
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_deregister_llm_execution_intercept(const char *name);

/**
 * Register an LLM streaming execution intercept following the middleware chain
 * pattern. The callback receives `(request, next_fn, next_ctx)` — call
 * `next_fn(request, next_ctx)` to invoke the next intercept or the original
 * streaming LLM call, or skip calling it to short-circuit.
 *
 * # Parameters
 * - `name`: Unique intercept name.
 * - `priority`: Execution priority (lower runs first).
 * - `exec_cb`: Middleware callback receiving request and a next function.
 * - `exec_user_data`: Opaque pointer for the execution callback.
 * - `exec_free`: Optional destructor for `exec_user_data`.
 *
 * # Safety
 * `name` must be a valid C string. Callback pointers must be valid.
 */
NemoFlowStatus nemo_flow_register_llm_stream_execution_intercept(const char *name,
                                                                 int32_t priority,
                                                                 NemoFlowLlmExecInterceptCb exec_cb,
                                                                 void *exec_user_data,
                                                                 NemoFlowFreeFn exec_free);

/**
 * Deregister an LLM streaming execution intercept by name.
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_deregister_llm_stream_execution_intercept(const char *name);

/**
 * Register an event subscriber. The callback is invoked for every lifecycle
 * event emitted by the runtime.
 *
 * # Parameters
 * - `name`: Unique subscriber name.
 * - `cb`: Event callback. The `FfiEvent` is valid only during the call.
 * - `user_data`: Opaque pointer passed to `cb`.
 * - `free_fn`: Optional destructor for `user_data`.
 *
 * # Safety
 * `name` must be a valid C string. `cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_register_subscriber(const char *name,
                                             NemoFlowEventSubscriberCb cb,
                                             void *user_data,
                                             NemoFlowFreeFn free_fn);

/**
 * Deregister an event subscriber by name.
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_deregister_subscriber(const char *name);

/**
 * Return the built-in observability plugin kind.
 *
 * The caller owns the returned string and must free it with `nemo_flow_string_free`.
 */
char *nemo_flow_observability_plugin_kind(void);

/**
 * Return the default observability plugin config as JSON.
 *
 * # Safety
 * `out_json` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_observability_default_config_json(char **out_json);

/**
 * Wrap an observability config JSON object as a top-level plugin component.
 *
 * Pass null for `config_json` to use the default observability config. The
 * returned JSON can be inserted into `PluginConfig.components`.
 *
 * # Safety
 * `config_json`, when non-null, must be a valid C string. `out_json` must be a
 * valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_observability_component_spec_json(const char *config_json,
                                                           bool enabled,
                                                           char **out_json);

/**
 * Creates a new ATIF exporter.
 *
 * # Parameters
 * - `session_id`: Session identifier string (required, non-null).
 * - `agent_name`: Agent name string (required, non-null).
 * - `agent_version`: Agent version string (required, non-null).
 * - `model_name`: Default model name (nullable).
 * - `out`: On success, receives a heap-allocated `FfiAtifExporter`.
 *
 * # Safety
 * All non-null string pointers must be valid C strings. `out` must be valid.
 */
NemoFlowStatus nemo_flow_atif_exporter_create(const char *session_id,
                                              const char *agent_name,
                                              const char *agent_version,
                                              const char *model_name,
                                              struct FfiAtifExporter **out);

/**
 * Registers the exporter as an event subscriber.
 *
 * # Parameters
 * - `exporter`: The exporter handle.
 * - `name`: Subscriber name (required, non-null).
 *
 * # Safety
 * `exporter` and `name` must be valid, non-null pointers.
 */
NemoFlowStatus nemo_flow_atif_exporter_register(const struct FfiAtifExporter *exporter,
                                                const char *name);

/**
 * Deregisters the exporter subscriber.
 *
 * # Parameters
 * - `name`: Subscriber name (required, non-null).
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_atif_exporter_deregister(const char *name);

/**
 * Exports collected events as an ATIF trajectory JSON string.
 *
 * # Parameters
 * - `exporter`: The exporter handle.
 * - `out`: On success, receives a JSON string (caller must free with
 *   `nemo_flow_string_free`).
 *
 * # Safety
 * `exporter` and `out` must be valid, non-null pointers.
 */
NemoFlowStatus nemo_flow_atif_exporter_export(const struct FfiAtifExporter *exporter, char **out);

/**
 * Clears all collected events from the exporter.
 *
 * # Parameters
 * - `exporter`: The exporter handle.
 *
 * # Safety
 * `exporter` must be a valid, non-null `FfiAtifExporter` pointer.
 */
NemoFlowStatus nemo_flow_atif_exporter_clear(const struct FfiAtifExporter *exporter);

/**
 * Creates a new filesystem-backed ATOF JSONL exporter.
 *
 * # Parameters
 * - `output_directory`: Output directory path (nullable for current directory).
 * - `mode`: `"append"` or `"overwrite"` (nullable for `"append"`).
 * - `filename`: Output filename (nullable for generated default).
 * - `out`: On success, receives a heap-allocated `FfiAtofExporter`.
 *
 * # Safety
 * All non-null string pointers must be valid C strings. `out` must be valid.
 */
NemoFlowStatus nemo_flow_atof_exporter_create(const char *output_directory,
                                              const char *mode,
                                              const char *filename,
                                              struct FfiAtofExporter **out);

/**
 * Registers the ATOF exporter as an event subscriber.
 *
 * # Safety
 * `exporter` and `name` must be valid, non-null pointers.
 */
NemoFlowStatus nemo_flow_atof_exporter_register(const struct FfiAtofExporter *exporter,
                                                const char *name);

/**
 * Deregisters the ATOF exporter subscriber.
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_atof_exporter_deregister(const char *name);

/**
 * Flushes the ATOF exporter output file.
 *
 * # Safety
 * `exporter` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_atof_exporter_force_flush(const struct FfiAtofExporter *exporter);

/**
 * Shuts down the ATOF exporter by flushing output.
 *
 * # Safety
 * `exporter` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_atof_exporter_shutdown(const struct FfiAtofExporter *exporter);

/**
 * Returns the ATOF exporter output path as a string.
 *
 * # Safety
 * `exporter` and `out` must be valid, non-null pointers.
 */
NemoFlowStatus nemo_flow_atof_exporter_path(const struct FfiAtofExporter *exporter, char **out);

/**
 * Creates a new OpenTelemetry subscriber.
 *
 * Nullable strings use crate defaults when omitted. `headers_json` and
 * `resource_attributes_json` must be JSON objects of string values when
 * provided.
 *
 * # Safety
 * Any non-null C strings must be valid and `out` must be non-null.
 */
NemoFlowStatus nemo_flow_otel_subscriber_create(const char *transport,
                                                const char *endpoint,
                                                const char *headers_json,
                                                const char *resource_attributes_json,
                                                const char *service_name,
                                                const char *service_namespace,
                                                const char *service_version,
                                                const char *instrumentation_scope,
                                                uint64_t timeout_millis,
                                                struct FfiOpenTelemetrySubscriber **out);

/**
 * Registers the OpenTelemetry subscriber as an event subscriber.
 *
 * # Safety
 * `subscriber` and `name` must be valid, non-null pointers.
 */
NemoFlowStatus nemo_flow_otel_subscriber_register(const struct FfiOpenTelemetrySubscriber *subscriber,
                                                  const char *name);

/**
 * Deregisters the OpenTelemetry subscriber by name.
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_otel_subscriber_deregister(const char *name);

/**
 * Forces a flush of finished spans through the exporter.
 *
 * # Safety
 * `subscriber` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_otel_subscriber_force_flush(const struct FfiOpenTelemetrySubscriber *subscriber);

/**
 * Shuts down the underlying tracer provider.
 *
 * # Safety
 * `subscriber` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_otel_subscriber_shutdown(const struct FfiOpenTelemetrySubscriber *subscriber);

/**
 * Creates a new OpenInference subscriber.
 *
 * Nullable strings use crate defaults when omitted. `headers_json` and
 * `resource_attributes_json` must be JSON objects of string values when
 * provided.
 *
 * # Safety
 * Any non-null C strings must be valid and `out` must be non-null.
 */
NemoFlowStatus nemo_flow_openinference_subscriber_create(const char *transport,
                                                         const char *endpoint,
                                                         const char *headers_json,
                                                         const char *resource_attributes_json,
                                                         const char *service_name,
                                                         const char *service_namespace,
                                                         const char *service_version,
                                                         const char *instrumentation_scope,
                                                         uint64_t timeout_millis,
                                                         struct FfiOpenInferenceSubscriber **out);

/**
 * Registers the OpenInference subscriber as an event subscriber.
 *
 * # Safety
 * `subscriber` and `name` must be valid, non-null pointers.
 */
NemoFlowStatus nemo_flow_openinference_subscriber_register(const struct FfiOpenInferenceSubscriber *subscriber,
                                                           const char *name);

/**
 * Deregisters the OpenInference subscriber by name.
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_openinference_subscriber_deregister(const char *name);

/**
 * Forces a flush of finished spans through the exporter.
 *
 * # Safety
 * `subscriber` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_openinference_subscriber_force_flush(const struct FfiOpenInferenceSubscriber *subscriber);

/**
 * Shuts down the underlying tracer provider.
 *
 * # Safety
 * `subscriber` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_openinference_subscriber_shutdown(const struct FfiOpenInferenceSubscriber *subscriber);

/**
 * Validate a generic plugin config document and return the diagnostics report as JSON.
 *
 * # Safety
 * `config_json` must be a valid C string and `out_json` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_validate_plugin_config(const char *config_json, char **out_json);

/**
 * Initialize the active global plugin components and return the resulting diagnostics report.
 *
 * # Safety
 * `config_json` must be a valid C string and `out_json` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_initialize_plugins(const char *config_json, char **out_json);

/**
 * Clear the active global plugin configuration.
 */
NemoFlowStatus nemo_flow_clear_plugin_configuration(void);

/**
 * Return the last successfully configured plugin report as JSON.
 *
 * # Safety
 * `out_json` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_active_plugin_report_json(char **out_json);

/**
 * Return the registered plugin kinds as JSON.
 *
 * # Safety
 * `out_json` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_list_plugin_kinds_json(char **out_json);

/**
 * Register a plugin backed by foreign callbacks.
 *
 * # Safety
 * `plugin_kind` must be a valid C string and `register_cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_register_plugin(const char *plugin_kind,
                                         struct Option_NemoFlowPluginValidateCb validate_cb,
                                         NemoFlowPluginRegisterCb register_cb,
                                         void *user_data,
                                         NemoFlowFreeFn free_fn);

/**
 * Deregister a plugin by kind.
 *
 * # Safety
 * `plugin_kind` must be a valid C string.
 */
NemoFlowStatus nemo_flow_deregister_plugin(const char *plugin_kind);

/**
 * Register an event subscriber into the plugin registration context.
 *
 * # Safety
 * `ctx` and `name` must be valid pointers and the callback must remain valid for the duration
 * of the plugin registration lifetime.
 */
NemoFlowStatus nemo_flow_plugin_context_register_subscriber(struct FfiPluginContext *ctx,
                                                            const char *name,
                                                            NemoFlowEventSubscriberCb cb,
                                                            void *user_data,
                                                            NemoFlowFreeFn free_fn);

/**
 * Register a tool sanitize-request guardrail into the plugin registration context.
 *
 * # Safety
 * `ctx` and `name` must be valid pointers and the callback must remain valid for the duration
 * of the plugin registration lifetime.
 */
NemoFlowStatus nemo_flow_plugin_context_register_tool_sanitize_request_guardrail(struct FfiPluginContext *ctx,
                                                                                 const char *name,
                                                                                 int32_t priority,
                                                                                 NemoFlowToolSanitizeCb cb,
                                                                                 void *user_data,
                                                                                 NemoFlowFreeFn free_fn);

/**
 * Register a tool sanitize-response guardrail into the plugin registration context.
 *
 * # Safety
 * `ctx` and `name` must be valid pointers and the callback must remain valid for the duration
 * of the plugin registration lifetime.
 */
NemoFlowStatus nemo_flow_plugin_context_register_tool_sanitize_response_guardrail(struct FfiPluginContext *ctx,
                                                                                  const char *name,
                                                                                  int32_t priority,
                                                                                  NemoFlowToolSanitizeCb cb,
                                                                                  void *user_data,
                                                                                  NemoFlowFreeFn free_fn);

/**
 * Register a tool conditional-execution guardrail into the plugin registration context.
 *
 * # Safety
 * `ctx` and `name` must be valid pointers and the callback must remain valid for the duration
 * of the plugin registration lifetime.
 */
NemoFlowStatus nemo_flow_plugin_context_register_tool_conditional_execution_guardrail(struct FfiPluginContext *ctx,
                                                                                      const char *name,
                                                                                      int32_t priority,
                                                                                      NemoFlowToolConditionalCb cb,
                                                                                      void *user_data,
                                                                                      NemoFlowFreeFn free_fn);

/**
 * Register an LLM sanitize-request guardrail into the plugin registration context.
 *
 * # Safety
 * `ctx` and `name` must be valid pointers and the callback must remain valid for the duration
 * of the plugin registration lifetime.
 */
NemoFlowStatus nemo_flow_plugin_context_register_llm_sanitize_request_guardrail(struct FfiPluginContext *ctx,
                                                                                const char *name,
                                                                                int32_t priority,
                                                                                NemoFlowLlmRequestCb cb,
                                                                                void *user_data,
                                                                                NemoFlowFreeFn free_fn);

/**
 * Register an LLM sanitize-response guardrail into the plugin registration context.
 *
 * # Safety
 * `ctx` and `name` must be valid pointers and the callback must remain valid for the duration
 * of the plugin registration lifetime.
 */
NemoFlowStatus nemo_flow_plugin_context_register_llm_sanitize_response_guardrail(struct FfiPluginContext *ctx,
                                                                                 const char *name,
                                                                                 int32_t priority,
                                                                                 NemoFlowJsonCb cb,
                                                                                 void *user_data,
                                                                                 NemoFlowFreeFn free_fn);

/**
 * Register an LLM conditional-execution guardrail into the plugin registration context.
 *
 * # Safety
 * `ctx` and `name` must be valid pointers and the callback must remain valid for the duration
 * of the plugin registration lifetime.
 */
NemoFlowStatus nemo_flow_plugin_context_register_llm_conditional_execution_guardrail(struct FfiPluginContext *ctx,
                                                                                     const char *name,
                                                                                     int32_t priority,
                                                                                     NemoFlowLlmConditionalCb cb,
                                                                                     void *user_data,
                                                                                     NemoFlowFreeFn free_fn);

/**
 * Register an LLM request intercept into the plugin registration context.
 *
 * # Safety
 * `ctx` and `name` must be valid pointers and the callback must remain valid for the duration
 * of the plugin registration lifetime.
 */
NemoFlowStatus nemo_flow_plugin_context_register_llm_request_intercept(struct FfiPluginContext *ctx,
                                                                       const char *name,
                                                                       int32_t priority,
                                                                       bool break_chain,
                                                                       NemoFlowLlmRequestInterceptCb cb,
                                                                       void *user_data,
                                                                       NemoFlowFreeFn free_fn);

/**
 * Register a tool request intercept into the plugin registration context.
 *
 * # Safety
 * `ctx` and `name` must be valid pointers and the callback must remain valid for the duration
 * of the plugin registration lifetime.
 */
NemoFlowStatus nemo_flow_plugin_context_register_tool_request_intercept(struct FfiPluginContext *ctx,
                                                                        const char *name,
                                                                        int32_t priority,
                                                                        bool break_chain,
                                                                        NemoFlowToolSanitizeCb cb,
                                                                        void *user_data,
                                                                        NemoFlowFreeFn free_fn);

/**
 * Register an LLM execution intercept into the plugin registration context.
 *
 * # Safety
 * `ctx` and `name` must be valid pointers and the callback must remain valid for the duration
 * of the plugin registration lifetime.
 */
NemoFlowStatus nemo_flow_plugin_context_register_llm_execution_intercept(struct FfiPluginContext *ctx,
                                                                         const char *name,
                                                                         int32_t priority,
                                                                         NemoFlowLlmExecInterceptCb cb,
                                                                         void *user_data,
                                                                         NemoFlowFreeFn free_fn);

/**
 * Register an LLM stream execution intercept into the plugin registration context.
 *
 * # Safety
 * `ctx` and `name` must be valid pointers and the callback must remain valid for the duration
 * of the plugin registration lifetime.
 */
NemoFlowStatus nemo_flow_plugin_context_register_llm_stream_execution_intercept(struct FfiPluginContext *ctx,
                                                                                const char *name,
                                                                                int32_t priority,
                                                                                NemoFlowLlmExecInterceptCb cb,
                                                                                void *user_data,
                                                                                NemoFlowFreeFn free_fn);

/**
 * Register a tool execution intercept into the plugin registration context.
 *
 * # Safety
 * `ctx` and `name` must be valid pointers and the callback must remain valid for the duration
 * of the plugin registration lifetime.
 */
NemoFlowStatus nemo_flow_plugin_context_register_tool_execution_intercept(struct FfiPluginContext *ctx,
                                                                          const char *name,
                                                                          int32_t priority,
                                                                          NemoFlowToolExecInterceptCb cb,
                                                                          void *user_data,
                                                                          NemoFlowFreeFn free_fn);

/**
 * Retrieve the current scope handle from the thread-local scope stack.
 *
 * # Parameters
 * - `out`: On success, receives a heap-allocated `FfiScopeHandle` that must be
 *   freed with `nemo_flow_scope_handle_free`.
 *
 * # Safety
 * `out` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_get_handle(struct FfiScopeHandle **out);

/**
 * Push a new scope onto the scope stack.
 *
 * This creates a scope handle, emits a scope Start event, and makes the new
 * scope the current top of the active stack.
 *
 * # Parameters
 * - `name`: Null-terminated scope name.
 * - `scope_type`: The type of scope to create.
 * - `parent`: Optional parent scope handle, or null to use the current top of
 *   stack.
 * - `attributes`: Bitfield of scope attributes.
 * - `data_json`: Optional null-terminated JSON string stored on the scope
 *   handle, or null.
 * - `metadata_json`: Optional null-terminated JSON metadata string recorded
 *   on the start event, or null.
 * - `input_json`: Optional null-terminated JSON string exported as the
 *   semantic scope input on the start event, or null.
 * - `timestamp_unix_micros`: Optional Unix microseconds timestamp for the
 *   handle start time and start event, or null to use the current UTC time.
 * - `out`: On success, receives a heap-allocated `FfiScopeHandle` that must
 *   be freed with `nemo_flow_scope_handle_free`.
 *
 * # Errors
 * Returns `InvalidJson` for invalid JSON inputs and `InvalidArg` when
 * `timestamp_unix_micros` is outside the supported timestamp range.
 *
 * # Safety
 * `name` must be a valid C string. `out` must be non-null. `parent`,
 * `data_json`, `metadata_json`, `input_json`, and `timestamp_unix_micros` may
 * be null; when non-null, optional pointers must be valid for reads for the
 * duration of the call.
 */
NemoFlowStatus nemo_flow_push_scope(const char *name,
                                    NemoFlowScopeType scope_type,
                                    const struct FfiScopeHandle *parent,
                                    uint32_t attributes,
                                    const char *data_json,
                                    const char *metadata_json,
                                    const char *input_json,
                                    const int64_t *timestamp_unix_micros,
                                    struct FfiScopeHandle **out);

/**
 * Pop a scope from the scope stack by its handle.
 *
 * This emits a scope End event and removes scope-local registrations owned by
 * the popped scope.
 *
 * # Parameters
 * - `handle`: The current top-of-stack scope handle to pop.
 * - `output_json`: Optional null-terminated JSON string exported as semantic
 *   scope output on the end event, or null.
 * - `timestamp_unix_micros`: Optional Unix microseconds timestamp for the end
 *   event, or null to use the runtime default end timestamp.
 *
 * # Errors
 * Returns `InvalidJson` for invalid output JSON, `InvalidArg` when
 * `timestamp_unix_micros` is outside the supported timestamp range, or an
 * error status when `handle` is not the current top scope.
 *
 * # Safety
 * `handle` must be a valid, non-null `FfiScopeHandle` pointer. `output_json` and
 * `timestamp_unix_micros` may be null; when non-null, optional pointers must
 * be valid for reads for the duration of the call.
 */
NemoFlowStatus nemo_flow_pop_scope(const struct FfiScopeHandle *handle,
                                   const char *output_json,
                                   const int64_t *timestamp_unix_micros);

/**
 * Emit a named lifecycle event.
 *
 * This creates a point-in-time Mark event without pushing or popping a scope.
 *
 * # Parameters
 * - `name`: Null-terminated event name.
 * - `parent`: Optional parent scope handle, or null to use the current top of
 *   stack.
 * - `data_json`: Optional null-terminated JSON data payload recorded on the
 *   mark event, or null.
 * - `metadata_json`: Optional null-terminated JSON metadata payload recorded
 *   on the mark event, or null.
 * - `timestamp_unix_micros`: Optional Unix microseconds timestamp for the
 *   mark event, or null to use the current UTC time.
 *
 * # Errors
 * Returns `InvalidJson` for invalid JSON inputs and `InvalidArg` when
 * `timestamp_unix_micros` is outside the supported timestamp range.
 *
 * # Safety
 * `name` must be a valid C string. Other pointer args may be null; when
 * non-null, optional pointers must be valid for reads for the duration of the
 * call.
 */
NemoFlowStatus nemo_flow_event(const char *name,
                               const struct FfiScopeHandle *parent,
                               const char *data_json,
                               const char *metadata_json,
                               const int64_t *timestamp_unix_micros);

/**
 * Register a scope-local tool conditional execution guardrail.
 *
 * # Parameters
 * - `scope_uuid`: UUID of the target scope (null-terminated C string).
 * - `name`: Unique guardrail name.
 * - `priority`: Execution priority (lower runs first).
 * - `cb`: Conditional callback.
 * - `user_data`: Opaque pointer passed to `cb`.
 * - `free_fn`: Optional destructor for `user_data`.
 *
 * The callback is fallible. To signal an internal callback failure instead of
 * allow/reject, call [`crate::error::nemo_flow_set_last_error_message`] from C
 * and return null.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings. `cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_scope_register_tool_conditional_execution_guardrail(const char *scope_uuid,
                                                                             const char *name,
                                                                             int32_t priority,
                                                                             NemoFlowToolConditionalCb cb,
                                                                             void *user_data,
                                                                             NemoFlowFreeFn free_fn);

/**
 * Deregister a scope-local tool conditional execution guardrail by name.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings.
 */
NemoFlowStatus nemo_flow_scope_deregister_tool_conditional_execution_guardrail(const char *scope_uuid,
                                                                               const char *name);

/**
 * Register a scope-local tool execution intercept following the middleware
 * chain pattern.
 *
 * # Parameters
 * - `scope_uuid`: UUID of the target scope (null-terminated C string).
 * - `name`: Unique intercept name.
 * - `priority`: Execution priority (lower runs first).
 * - `exec_cb`: Middleware callback receiving args and a next function.
 * - `exec_user_data`: Opaque pointer for the execution callback.
 * - `exec_free`: Optional destructor for `exec_user_data`.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings. Callback pointers must be valid.
 */
NemoFlowStatus nemo_flow_scope_register_tool_execution_intercept(const char *scope_uuid,
                                                                 const char *name,
                                                                 int32_t priority,
                                                                 NemoFlowToolExecInterceptCb exec_cb,
                                                                 void *exec_user_data,
                                                                 NemoFlowFreeFn exec_free);

/**
 * Deregister a scope-local tool execution intercept by name.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings.
 */
NemoFlowStatus nemo_flow_scope_deregister_tool_execution_intercept(const char *scope_uuid,
                                                                   const char *name);

/**
 * Register a scope-local LLM request sanitization guardrail.
 *
 * # Parameters
 * - `scope_uuid`: UUID of the target scope (null-terminated C string).
 * - `name`: Unique guardrail name.
 * - `priority`: Execution priority (lower runs first).
 * - `cb`: Request sanitize callback.
 * - `user_data`: Opaque pointer passed to `cb`.
 * - `free_fn`: Optional destructor for `user_data`.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings. `cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_scope_register_llm_sanitize_request_guardrail(const char *scope_uuid,
                                                                       const char *name,
                                                                       int32_t priority,
                                                                       NemoFlowLlmRequestCb cb,
                                                                       void *user_data,
                                                                       NemoFlowFreeFn free_fn);

/**
 * Deregister a scope-local LLM request sanitization guardrail by name.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings.
 */
NemoFlowStatus nemo_flow_scope_deregister_llm_sanitize_request_guardrail(const char *scope_uuid,
                                                                         const char *name);

/**
 * Register a scope-local LLM response sanitization guardrail.
 *
 * # Parameters
 * - `scope_uuid`: UUID of the target scope (null-terminated C string).
 * - `name`: Unique guardrail name.
 * - `priority`: Execution priority (lower runs first).
 * - `cb`: JSON-to-JSON callback.
 * - `user_data`: Opaque pointer passed to `cb`.
 * - `free_fn`: Optional destructor for `user_data`.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings. `cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_scope_register_llm_sanitize_response_guardrail(const char *scope_uuid,
                                                                        const char *name,
                                                                        int32_t priority,
                                                                        NemoFlowJsonCb cb,
                                                                        void *user_data,
                                                                        NemoFlowFreeFn free_fn);

/**
 * Deregister a scope-local LLM response sanitization guardrail by name.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings.
 */
NemoFlowStatus nemo_flow_scope_deregister_llm_sanitize_response_guardrail(const char *scope_uuid,
                                                                          const char *name);

/**
 * Register a scope-local LLM conditional execution guardrail.
 *
 * # Parameters
 * - `scope_uuid`: UUID of the target scope (null-terminated C string).
 * - `name`: Unique guardrail name.
 * - `priority`: Execution priority (lower runs first).
 * - `cb`: Conditional callback.
 * - `user_data`: Opaque pointer passed to `cb`.
 * - `free_fn`: Optional destructor for `user_data`.
 *
 * The callback is fallible. To signal an internal callback failure instead of
 * allow/reject, call [`crate::error::nemo_flow_set_last_error_message`] from C
 * and return null.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings. `cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_scope_register_llm_conditional_execution_guardrail(const char *scope_uuid,
                                                                            const char *name,
                                                                            int32_t priority,
                                                                            NemoFlowLlmConditionalCb cb,
                                                                            void *user_data,
                                                                            NemoFlowFreeFn free_fn);

/**
 * Deregister a scope-local LLM conditional execution guardrail by name.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings.
 */
NemoFlowStatus nemo_flow_scope_deregister_llm_conditional_execution_guardrail(const char *scope_uuid,
                                                                              const char *name);

/**
 * Register a scope-local LLM request intercept.
 *
 * # Parameters
 * - `scope_uuid`: UUID of the target scope (null-terminated C string).
 * - `name`: Unique intercept name.
 * - `priority`: Execution priority (lower runs first).
 * - `break_chain`: If true, stop processing further intercepts after this one.
 * - `cb`: LLM request transform callback.
 * - `user_data`: Opaque pointer passed to `cb`.
 * - `free_fn`: Optional destructor for `user_data`.
 *
 * The callback is fallible. To signal failure, call
 * [`crate::error::nemo_flow_set_last_error_message`] from C and return null.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings. `cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_scope_register_llm_request_intercept(const char *scope_uuid,
                                                              const char *name,
                                                              int32_t priority,
                                                              bool break_chain,
                                                              NemoFlowLlmRequestInterceptCb cb,
                                                              void *user_data,
                                                              NemoFlowFreeFn free_fn);

/**
 * Deregister a scope-local LLM request intercept by name.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings.
 */
NemoFlowStatus nemo_flow_scope_deregister_llm_request_intercept(const char *scope_uuid,
                                                                const char *name);

/**
 * Register a scope-local LLM execution intercept following the middleware
 * chain pattern.
 *
 * # Parameters
 * - `scope_uuid`: UUID of the target scope (null-terminated C string).
 * - `name`: Unique intercept name.
 * - `priority`: Execution priority (lower runs first).
 * - `exec_cb`: Middleware callback receiving request and a next function.
 * - `exec_user_data`: Opaque pointer for the execution callback.
 * - `exec_free`: Optional destructor for `exec_user_data`.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings. Callback pointers must be valid.
 */
NemoFlowStatus nemo_flow_scope_register_llm_execution_intercept(const char *scope_uuid,
                                                                const char *name,
                                                                int32_t priority,
                                                                NemoFlowLlmExecInterceptCb exec_cb,
                                                                void *exec_user_data,
                                                                NemoFlowFreeFn exec_free);

/**
 * Deregister a scope-local LLM execution intercept by name.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings.
 */
NemoFlowStatus nemo_flow_scope_deregister_llm_execution_intercept(const char *scope_uuid,
                                                                  const char *name);

/**
 * Register a scope-local LLM streaming execution intercept following the
 * middleware chain pattern.
 *
 * # Parameters
 * - `scope_uuid`: UUID of the target scope (null-terminated C string).
 * - `name`: Unique intercept name.
 * - `priority`: Execution priority (lower runs first).
 * - `exec_cb`: Middleware callback receiving request and a next function.
 * - `exec_user_data`: Opaque pointer for the execution callback.
 * - `exec_free`: Optional destructor for `exec_user_data`.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings. Callback pointers must be valid.
 */
NemoFlowStatus nemo_flow_scope_register_llm_stream_execution_intercept(const char *scope_uuid,
                                                                       const char *name,
                                                                       int32_t priority,
                                                                       NemoFlowLlmExecInterceptCb exec_cb,
                                                                       void *exec_user_data,
                                                                       NemoFlowFreeFn exec_free);

/**
 * Deregister a scope-local LLM streaming execution intercept by name.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings.
 */
NemoFlowStatus nemo_flow_scope_deregister_llm_stream_execution_intercept(const char *scope_uuid,
                                                                         const char *name);

/**
 * Register a scope-local event subscriber.
 *
 * # Parameters
 * - `scope_uuid`: UUID of the target scope (null-terminated C string).
 * - `name`: Unique subscriber name.
 * - `cb`: Event callback.
 * - `user_data`: Opaque pointer passed to `cb`.
 * - `free_fn`: Optional destructor for `user_data`.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings. `cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_scope_register_subscriber(const char *scope_uuid,
                                                   const char *name,
                                                   NemoFlowEventSubscriberCb cb,
                                                   void *user_data,
                                                   NemoFlowFreeFn free_fn);

/**
 * Deregister a scope-local event subscriber by name.
 *
 * # Safety
 * `scope_uuid` and `name` must be valid C strings.
 */
NemoFlowStatus nemo_flow_scope_deregister_subscriber(const char *scope_uuid, const char *name);

/**
 * Create a new isolated scope stack with its own root scope.
 *
 * Each scope stack is independent: scopes pushed on one do not appear on another.
 * Use `nemo_flow_scope_stack_set_thread` to bind a stack to the current thread
 * before making other NeMo Flow API calls.
 *
 * # Parameters
 * - `out`: On success, receives a heap-allocated `FfiScopeStack` that must be
 *   freed with `nemo_flow_scope_stack_free`.
 *
 * # Returns
 * - Returns [`NemoFlowStatus::Ok`] on success and writes the new scope stack
 *   to `out`.
 * - Returns [`NemoFlowStatus::NullPointer`] when `out` is null.
 *
 * # Safety
 * `out` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_scope_stack_create(struct FfiScopeStack **out);

/**
 * Bind an isolated scope stack to the current OS thread.
 *
 * After this call, all NeMo Flow scope operations on the current thread
 * (e.g. `nemo_flow_push_scope`, `nemo_flow_get_handle`) will use the
 * given scope stack. This is typically used from Go goroutines that have
 * called `runtime.LockOSThread()`.
 *
 * The `FfiScopeStack` is **not** consumed — the caller retains ownership
 * and must still free it when done.
 *
 * # Parameters
 * - `stack`: Scope stack to bind to the current OS thread.
 *
 * # Returns
 * - Returns [`NemoFlowStatus::Ok`] when the thread-local scope stack was
 *   updated successfully.
 * - Returns [`NemoFlowStatus::NullPointer`] when `stack` is null.
 *
 * # Safety
 * `stack` must be a valid, non-null `FfiScopeStack` pointer.
 */
NemoFlowStatus nemo_flow_scope_stack_set_thread(const struct FfiScopeStack *stack);

/**
 * Capture the current thread-local scope stack binding.
 *
 * The returned binding must be restored with
 * `nemo_flow_scope_stack_restore_thread`.
 *
 * # Parameters
 * - `out`: On success, receives a heap-allocated binding handle.
 *
 * # Safety
 * `out` must be a valid, non-null pointer.
 */
NemoFlowStatus nemo_flow_scope_stack_capture_thread(struct FfiThreadScopeStackBinding **out);

/**
 * Restore and free a captured thread-local scope stack binding.
 *
 * # Safety
 * `binding` must be a valid pointer returned by
 * `nemo_flow_scope_stack_capture_thread`.
 */
NemoFlowStatus nemo_flow_scope_stack_restore_thread(struct FfiThreadScopeStackBinding *binding);

/**
 * Returns whether the current execution context has an explicitly-initialized
 * scope stack.
 *
 * Returns `true` if `nemo_flow_scope_stack_set_thread` has been called on the
 * current OS thread (or the caller is inside a tokio task-local scope).
 * Returns `false` when only the auto-created default is present.
 *
 * # Notes
 * This helper does not allocate or install a scope stack. It only reports
 * whether one is already explicit in the current execution context.
 */
bool nemo_flow_scope_stack_active(void);

/**
 * Begin a manual tool call lifecycle span.
 *
 * This emits a tool Start event after applying sanitize-request guardrails to
 * the observability payload. Request and execution intercepts only run through
 * `nemo_flow_tool_call_execute`.
 *
 * # Parameters
 * - `name`: Null-terminated tool name.
 * - `args_json`: Tool arguments as a null-terminated JSON C string. These
 *   arguments become the start-event data after sanitize-request guardrails.
 * - `parent`: Optional parent scope handle, or null to use the current top of
 *   stack.
 * - `attributes`: Bitfield of tool attributes.
 * - `data_json`: Optional null-terminated JSON string stored on the tool
 *   handle, or null.
 * - `metadata_json`: Optional null-terminated JSON metadata string recorded
 *   on the start event, or null.
 * - `tool_call_id`: Optional null-terminated external correlation ID recorded
 *   in the tool event category profile, or null.
 * - `timestamp_unix_micros`: Optional Unix microseconds timestamp for the
 *   handle start time and start event, or null to use the current UTC time.
 * - `out`: On success, receives a heap-allocated `FfiToolHandle` that must be
 *   freed with `nemo_flow_tool_handle_free`.
 *
 * # Errors
 * Returns `InvalidJson` for invalid JSON inputs and `InvalidArg` when
 * `timestamp_unix_micros` is outside the supported timestamp range.
 *
 * # Safety
 * `name` and `args_json` must be valid C strings. `out` must be non-null.
 * Optional pointer arguments may be null; when non-null, they must be valid
 * for reads for the duration of the call.
 */
NemoFlowStatus nemo_flow_tool_call(const char *name,
                                   const char *args_json,
                                   const struct FfiScopeHandle *parent,
                                   uint32_t attributes,
                                   const char *data_json,
                                   const char *metadata_json,
                                   const char *tool_call_id,
                                   const int64_t *timestamp_unix_micros,
                                   struct FfiToolHandle **out);

/**
 * End a manual tool call lifecycle span.
 *
 * This emits a tool End event after applying sanitize-response guardrails to
 * the observability payload. Response intercepts only run through
 * `nemo_flow_tool_call_execute`.
 *
 * # Parameters
 * - `handle`: The tool handle from `nemo_flow_tool_call`.
 * - `result_json`: Tool result as a null-terminated JSON C string. This
 *   result becomes the end-event data after sanitize-response guardrails unless
 *   it sanitizes to JSON null.
 * - `data_json`: Optional null-terminated JSON data used when the sanitized
 *   result is JSON null, or null.
 * - `metadata_json`: Optional null-terminated JSON metadata recorded on the
 *   end event, or null.
 * - `timestamp_unix_micros`: Optional Unix microseconds timestamp for the end
 *   event, or null to use the runtime default end timestamp.
 *
 * # Errors
 * Returns `InvalidJson` for invalid JSON inputs and `InvalidArg` when
 * `timestamp_unix_micros` is outside the supported timestamp range.
 *
 * # Safety
 * `handle` and `result_json` must be valid, non-null pointers. Optional
 * pointer arguments may be null; when non-null, they must be valid for reads
 * for the duration of the call.
 */
NemoFlowStatus nemo_flow_tool_call_end(const struct FfiToolHandle *handle,
                                       const char *result_json,
                                       const char *data_json,
                                       const char *metadata_json,
                                       const int64_t *timestamp_unix_micros);

/**
 * Execute a tool call end-to-end: run conditional-execution guardrails (on raw
 * args), then request intercepts, sanitize-request guardrails, execution
 * intercepts, the callback, and sanitize-response
 * guardrails. On rejection, only a standalone Mark event is emitted (no
 * Start/End pair) and `GuardrailRejected` is returned. Blocks the calling
 * thread until completion.
 *
 * # Parameters
 * - `name`: Null-terminated tool name.
 * - `args_json`: Tool arguments as a JSON C string.
 * - `func`: C callback that performs the actual tool execution.
 * - `func_user_data`: Opaque pointer passed to `func`.
 * - `func_free`: Optional destructor for `func_user_data`.
 * - `parent`: Optional parent scope handle, or null.
 * - `attributes`: Bitfield of tool attributes.
 * - `data_json`: Optional JSON data, or null.
 * - `metadata_json`: Optional JSON metadata, or null.
 * - `out`: On success, receives the result as a JSON C string. Caller must free
 *   with `nemo_flow_string_free`.
 *
 * # Safety
 * `name`, `args_json`, and `out` must be valid, non-null pointers.
 */
NemoFlowStatus nemo_flow_tool_call_execute(const char *name,
                                           const char *args_json,
                                           NemoFlowToolExecCb func,
                                           void *func_user_data,
                                           NemoFlowFreeFn func_free,
                                           const struct FfiScopeHandle *parent,
                                           uint32_t attributes,
                                           const char *data_json,
                                           const char *metadata_json,
                                           char **out);

/**
 * Register a tool conditional execution guardrail. The callback decides whether
 * a tool call should proceed. Returns an error message to reject, or null to allow.
 *
 * # Parameters
 * - `name`: Unique guardrail name.
 * - `priority`: Execution priority (lower runs first).
 * - `cb`: Conditional callback.
 * - `user_data`: Opaque pointer passed to `cb`.
 * - `free_fn`: Optional destructor for `user_data`.
 *
 * The callback is fallible. To signal an internal callback failure instead of
 * allow/reject, call [`crate::error::nemo_flow_set_last_error_message`] from C
 * and return null.
 *
 * # Safety
 * `name` must be a valid C string. `cb` must be a valid function pointer.
 */
NemoFlowStatus nemo_flow_register_tool_conditional_execution_guardrail(const char *name,
                                                                       int32_t priority,
                                                                       NemoFlowToolConditionalCb cb,
                                                                       void *user_data,
                                                                       NemoFlowFreeFn free_fn);

/**
 * Deregister a tool conditional execution guardrail by name.
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_deregister_tool_conditional_execution_guardrail(const char *name);

/**
 * Register a tool execution intercept following the middleware chain pattern.
 * The callback receives `(args, next_fn, next_ctx)` — call
 * `next_fn(args, next_ctx)` to invoke the next intercept or the original
 * tool function, or skip calling it to short-circuit.
 *
 * # Parameters
 * - `name`: Unique intercept name.
 * - `priority`: Execution priority (lower runs first).
 * - `exec_cb`: Middleware callback receiving args and a next function.
 * - `exec_user_data`: Opaque pointer for the execution callback.
 * - `exec_free`: Optional destructor for `exec_user_data`.
 *
 * # Safety
 * `name` must be a valid C string. Callback pointers must be valid.
 */
NemoFlowStatus nemo_flow_register_tool_execution_intercept(const char *name,
                                                           int32_t priority,
                                                           NemoFlowToolExecInterceptCb exec_cb,
                                                           void *exec_user_data,
                                                           NemoFlowFreeFn exec_free);

/**
 * Deregister a tool execution intercept by name.
 *
 * # Safety
 * `name` must be a valid C string.
 */
NemoFlowStatus nemo_flow_deregister_tool_execution_intercept(const char *name);

/**
 * Free a C string previously returned by any `nemo_flow_*` accessor function.
 * Passing null is a safe no-op.
 *
 * # Safety
 * `ptr` must be a pointer returned by this library, or null. Double-free is
 * undefined behavior.
 */
void nemo_flow_string_free(char *ptr);

/**
 * Retrieve the last error message set on this thread, or null if no error
 * has occurred since the last [`clear_last_error`] call.
 *
 * The returned pointer borrows from thread-local storage and is valid only
 * until the next FFI call on the same thread. Do **not** free the returned
 * pointer.
 */
const char *nemo_flow_last_error(void);

/**
 * Set the thread-local last-error message from foreign code.
 *
 * Intended for callback trampolines that need to propagate an error through
 * the existing FFI last-error channel.
 *
 * # Safety
 * `msg` must be either null or a valid, null-terminated C string for the
 * duration of this call.
 */
void nemo_flow_set_last_error_message(const char *msg);

/**
 * Free a scope handle previously returned by the runtime.
 *
 * # Safety
 * `ptr` must be a valid pointer returned by an `nemo_flow_*` function, or null.
 */
void nemo_flow_scope_handle_free(struct FfiScopeHandle *ptr);

/**
 * Free a tool handle previously returned by the runtime.
 *
 * # Safety
 * `ptr` must be a valid pointer returned by an `nemo_flow_*` function, or null.
 */
void nemo_flow_tool_handle_free(struct FfiToolHandle *ptr);

/**
 * Free an LLM handle previously returned by the runtime.
 *
 * # Safety
 * `ptr` must be a valid pointer returned by an `nemo_flow_*` function, or null.
 */
void nemo_flow_llm_handle_free(struct FfiLLMHandle *ptr);

/**
 * Free an LLM request object.
 *
 * # Safety
 * `ptr` must be a valid pointer returned by an `nemo_flow_*` function, or null.
 */
void nemo_flow_llm_request_free(struct FfiLLMRequest *ptr);

/**
 * Free an event object.
 *
 * # Safety
 * `ptr` must be a valid pointer returned by an `nemo_flow_*` function, or null.
 */
void nemo_flow_event_free(struct FfiEvent *ptr);

/**
 * Free a scope stack handle previously returned by `nemo_flow_scope_stack_create`.
 *
 * # Safety
 * `ptr` must be a valid pointer returned by `nemo_flow_scope_stack_create`, or null.
 */
void nemo_flow_scope_stack_free(struct FfiScopeStack *ptr);

/**
 * Free an ATIF exporter handle previously returned by `nemo_flow_atif_exporter_create`.
 *
 * # Safety
 * `ptr` must be a valid pointer returned by `nemo_flow_atif_exporter_create`, or null.
 */
void nemo_flow_atif_exporter_free(struct FfiAtifExporter *ptr);

/**
 * Free an ATOF JSONL exporter handle previously returned by `nemo_flow_atof_exporter_create`.
 *
 * # Safety
 * `ptr` must be a valid pointer returned by `nemo_flow_atof_exporter_create`, or null.
 */
void nemo_flow_atof_exporter_free(struct FfiAtofExporter *ptr);

/**
 * Free an OpenTelemetry subscriber handle previously returned by
 * `nemo_flow_otel_subscriber_create`.
 *
 * # Safety
 * `ptr` must be a valid pointer returned by `nemo_flow_otel_subscriber_create`, or null.
 */
void nemo_flow_otel_subscriber_free(struct FfiOpenTelemetrySubscriber *ptr);

/**
 * Free an OpenInference subscriber handle previously returned by
 * `nemo_flow_openinference_subscriber_create`.
 *
 * # Safety
 * `ptr` must be a valid pointer returned by
 * `nemo_flow_openinference_subscriber_create`, or null.
 */
void nemo_flow_openinference_subscriber_free(struct FfiOpenInferenceSubscriber *ptr);

/**
 * Free a codec handle previously returned by one of the codec constructor
 * functions (`nemo_flow_openai_chat_codec_new`, etc.).
 *
 * # Safety
 * `handle` must be a valid pointer returned by one of the codec constructor
 * functions, or null. Double-free is undefined behavior.
 */
void nemo_flow_codec_free(struct FfiCodecHandle *handle);

/**
 * Return the UUID of a scope handle as a C string. Caller must free the result
 * with `nemo_flow_string_free`. Returns null if `ptr` is null.
 *
 * # Safety
 * `ptr` must be a valid `FfiScopeHandle` pointer or null.
 */
char *nemo_flow_scope_handle_uuid(const struct FfiScopeHandle *ptr);

/**
 * Return the name of a scope handle as a C string. Caller must free the result.
 * Returns null if `ptr` is null.
 *
 * # Safety
 * `ptr` must be a valid `FfiScopeHandle` pointer or null.
 */
char *nemo_flow_scope_handle_name(const struct FfiScopeHandle *ptr);

/**
 * Return the scope type of a scope handle. Returns `Unknown` if `ptr` is null.
 *
 * # Safety
 * `ptr` must be a valid `FfiScopeHandle` pointer or null.
 */
NemoFlowScopeType nemo_flow_scope_handle_scope_type(const struct FfiScopeHandle *ptr);

/**
 * Return the bitfield attributes of a scope handle. Returns 0 if `ptr` is null.
 *
 * # Safety
 * `ptr` must be a valid `FfiScopeHandle` pointer or null.
 */
uint32_t nemo_flow_scope_handle_attributes(const struct FfiScopeHandle *ptr);

/**
 * Return the parent scope UUID as a C string, or null if there is no parent.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiScopeHandle` pointer or null.
 */
char *nemo_flow_scope_handle_parent_uuid(const struct FfiScopeHandle *ptr);

/**
 * Return the scope data as a JSON C string, or null if no data is set.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiScopeHandle` pointer or null.
 */
char *nemo_flow_scope_handle_data(const struct FfiScopeHandle *ptr);

/**
 * Return the scope metadata as a JSON C string, or null if no metadata is set.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiScopeHandle` pointer or null.
 */
char *nemo_flow_scope_handle_metadata(const struct FfiScopeHandle *ptr);

/**
 * Return the UUID of a tool handle as a C string. Caller must free the result.
 *
 * # Safety
 * `ptr` must be a valid `FfiToolHandle` pointer or null.
 */
char *nemo_flow_tool_handle_uuid(const struct FfiToolHandle *ptr);

/**
 * Return the name of a tool handle as a C string. Caller must free the result.
 *
 * # Safety
 * `ptr` must be a valid `FfiToolHandle` pointer or null.
 */
char *nemo_flow_tool_handle_name(const struct FfiToolHandle *ptr);

/**
 * Return the bitfield attributes of a tool handle. Returns 0 if `ptr` is null.
 *
 * # Safety
 * `ptr` must be a valid `FfiToolHandle` pointer or null.
 */
uint32_t nemo_flow_tool_handle_attributes(const struct FfiToolHandle *ptr);

/**
 * Return the parent scope UUID of a tool handle, or null if none.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiToolHandle` pointer or null.
 */
char *nemo_flow_tool_handle_parent_uuid(const struct FfiToolHandle *ptr);

/**
 * Return the UUID of an LLM handle as a C string. Caller must free the result.
 *
 * # Safety
 * `ptr` must be a valid `FfiLLMHandle` pointer or null.
 */
char *nemo_flow_llm_handle_uuid(const struct FfiLLMHandle *ptr);

/**
 * Return the name of an LLM handle as a C string. Caller must free the result.
 *
 * # Safety
 * `ptr` must be a valid `FfiLLMHandle` pointer or null.
 */
char *nemo_flow_llm_handle_name(const struct FfiLLMHandle *ptr);

/**
 * Return the bitfield attributes of an LLM handle. Returns 0 if `ptr` is null.
 *
 * # Safety
 * `ptr` must be a valid `FfiLLMHandle` pointer or null.
 */
uint32_t nemo_flow_llm_handle_attributes(const struct FfiLLMHandle *ptr);

/**
 * Return the parent scope UUID of an LLM handle, or null if none.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiLLMHandle` pointer or null.
 */
char *nemo_flow_llm_handle_parent_uuid(const struct FfiLLMHandle *ptr);

/**
 * Create a new LLM request object. Returns a heap-allocated `FfiLLMRequest`
 * that must be freed with `nemo_flow_llm_request_free`. Returns null on
 * invalid input.
 *
 * # Parameters
 * - `headers_json`: JSON object of headers/metadata, or null.
 * - `content_json`: JSON request content payload, or null.
 *
 * # Safety
 * All string arguments must be valid null-terminated C strings or null.
 */
struct FfiLLMRequest *nemo_flow_llm_request_new(const char *headers_json, const char *content_json);

/**
 * Return the headers of an LLM request as a JSON C string. Caller must free the result.
 *
 * # Safety
 * `ptr` must be a valid `FfiLLMRequest` pointer or null.
 */
char *nemo_flow_llm_request_headers(const struct FfiLLMRequest *ptr);

/**
 * Return the content of an LLM request as a JSON C string. Caller must free the result.
 *
 * # Safety
 * `ptr` must be a valid `FfiLLMRequest` pointer or null.
 */
char *nemo_flow_llm_request_content(const struct FfiLLMRequest *ptr);

/**
 * Return the UUID of an event as a C string. Caller must free the result.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_uuid(const struct FfiEvent *ptr);

/**
 * Return the name of an event as a C string, or null if unnamed.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_name(const struct FfiEvent *ptr);

/**
 * Return the event discriminator as a C string.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_kind(const struct FfiEvent *ptr);

/**
 * Return the canonical subscriber event JSON as a C string.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_json(const struct FfiEvent *ptr);

/**
 * Return the ATOF version as a C string.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_atof_version(const struct FfiEvent *ptr);

/**
 * Return the ATOF scope category as a C string, or null for mark events.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_scope_category(const struct FfiEvent *ptr);

/**
 * Return the ATOF category as a C string, or null if absent.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_category(const struct FfiEvent *ptr);

/**
 * Return ATOF attributes as a JSON string array.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_attributes_json(const struct FfiEvent *ptr);

/**
 * Return the ATOF category profile as a JSON C string, or null if absent.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_category_profile(const struct FfiEvent *ptr);

/**
 * Return the Agent Trajectory Observability Format (ATOF) data schema as a
 * JSON C string, or null if absent.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_data_schema(const struct FfiEvent *ptr);

/**
 * Return the raw attribute bitfield for an event, or 0 if it has none.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
uint32_t nemo_flow_event_attributes(const struct FfiEvent *ptr);

/**
 * Return the event data as a JSON C string, or null if no data is set.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_data(const struct FfiEvent *ptr);

/**
 * Return the event metadata as a JSON C string, or null if no metadata is set.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_metadata(const struct FfiEvent *ptr);

/**
 * Return the event timestamp as an RFC 3339 C string. Caller must free the result.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_timestamp(const struct FfiEvent *ptr);

/**
 * Return the event input as a JSON C string, or null if no input is set.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_input(const struct FfiEvent *ptr);

/**
 * Return the event output as a JSON C string, or null if no output is set.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_output(const struct FfiEvent *ptr);

/**
 * Return the event model name as a C string, or null if no model name is set.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_model_name(const struct FfiEvent *ptr);

/**
 * Return the event tool call ID as a C string, or null if no tool call ID is set.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_tool_call_id(const struct FfiEvent *ptr);

/**
 * Return the event parent UUID as a C string, or null if no parent UUID is set.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_parent_uuid(const struct FfiEvent *ptr);

/**
 * Return the event scope type as a C string, or null if no scope type is set.
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_scope_type(const struct FfiEvent *ptr);

/**
 * Return the annotated request from an LLM start event as a JSON C string,
 * or null if not available (non-LLM events, or no codec was active).
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_annotated_request(const struct FfiEvent *ptr);

/**
 * Return the annotated response from an LLM end event as a JSON C string,
 * or null if not available (non-LLM events, or no response codec was active).
 * Caller must free the result with `nemo_flow_string_free`.
 *
 * # Safety
 * `ptr` must be a valid `FfiEvent` pointer or null.
 */
char *nemo_flow_event_annotated_response(const struct FfiEvent *ptr);

#endif  /* NEMO_FLOW_H */
