|
Entropic 2.14.3
Local-first agentic inference engine
|
Core agent execution engine. More...
#include <entropic/core/engine.h>
Classes | |
| struct | DelegationCallbacks |
| Grouped consumer-registered delegation callbacks (gh#29). More... | |
Public Member Functions | |
| AgentEngine (const InferenceInterface &inference, const LoopConfig &loop_config, const CompactionConfig &compaction_config) | |
| Construct an agent engine. | |
| std::vector< Message > | run (std::vector< Message > messages, const std::string &tier_override="") |
| Run the engine on a set of messages. | |
| void | set_callbacks (const EngineCallbacks &callbacks) |
| Set callback functions for loop events. | |
| void | set_tool_executor (const ToolExecutionInterface &tool_exec) |
| Set the tool execution interface. | |
| void | set_tier_resolution (const TierResolutionInterface &tier_res) |
| Set the tier resolution interface for delegation. | |
| void | set_storage (const StorageInterface &storage) |
| Set the storage interface for persistence. | |
| void | set_hooks (const HookInterface &hooks) |
| Set the hook dispatch interface. | |
| void | set_project_dir (const std::filesystem::path &project_dir) |
| Set the configured project directory (gh#31, v2.1.6). | |
| void | set_session_root_interface (const SessionRootInterface &iface) |
| Inject the session-root / tool-reach seam (gh#160, v2.13.0). | |
| void | set_dir_swap (ScopedSandbox::SwapDirFn swap_fn, void *user_data) |
| Install the directory-swap callback used by sandboxing. | |
| std::filesystem::path | resolve_session_root (const std::string &session_key) |
| Resolve the root a session's tools operate in (gh#160). | |
| SandboxManager * | sandbox_for_session (const std::string &session_key) |
| Sandbox manager for a session, or nullptr when isolation is off (gh#160). | |
| std::vector< std::string > | isolation_unsafe_tools (const LoopContext &ctx, const std::string &target_tier) |
| Child-visible external tools that break the isolation claim. | |
| void | set_stream_observer (TokenCallback observer, void *user_data) |
| Set the global stream observer. | |
| void | set_validation_provider (char *(*provider)(void *), void *user_data) |
| Register a JSON provider for the validation block in ON_COMPLETE hook context. | |
| void | set_delegation_callbacks (ent_decision_t(*on_start)(const ent_delegation_request_t *, void *), ent_decision_t(*on_complete)(const ent_delegation_result_t *, void *), void *user_data) |
| Register delegation start/complete callbacks (gh#29, v2.1.5). | |
| DelegationCallbacks | delegation_callbacks_snapshot () const |
| Atomically snapshot the registered delegation callbacks. | |
| void | set_external_interrupt (void(*cb)(void *user_data), void *user_data) |
| Register a callback invoked alongside interrupt(). | |
| void | set_external_reset (void(*cb)(void *user_data), void *user_data) |
| Register the external transport interrupt-release callback. | |
| void | run_loop (LoopContext &ctx, bool inherit_interrupt=false) |
| Run the engine loop on a pre-built context. | |
| const TierResolutionInterface & | tier_resolution () const |
| Get the tier resolution interface. | |
| void | interrupt () |
| Interrupt the running loop (thread-safe). | |
| void | reset_interrupt () |
| Reset interrupt flag for next run. | |
| void | pause () |
| Pause generation (thread-safe). | |
| void | cancel_pause () |
| Cancel pause and interrupt completely. | |
| std::pair< int, int > | context_usage (const std::vector< Message > &messages) const |
| Get context usage for a message list. | |
| EngineCallbacks & | callbacks () |
| Get mutable reference to engine callbacks. | |
| const LoopConfig & | loop_config () const |
| Get loop configuration. | |
| DirectiveProcessor & | directive_processor () |
| Get directive processor for external hook wiring. | |
| LoopMetrics | last_loop_metrics () const |
| Get metrics from the most recent completed run. | |
| std::unordered_map< std::string, LoopMetrics > | per_tier_metrics () const |
| Per-tier aggregated metrics since engine start. | |
| void | set_system_prompt (const std::string &prompt) |
| Set the system prompt for conversation state. | |
| void | set_session_logger (SessionLogger *logger) |
| Set session logger for model transcript logging. | |
| std::vector< Message > | run_turn (const std::string &input) |
| Run a single conversation turn (stateful). | |
| std::vector< Message > | run_turn_as (const std::string &tier, const std::string &input) |
| Run a single turn under a named tier's grammar/identity (gh#99). | |
| std::vector< Message > | run_turn (std::vector< Message > new_messages) |
| Run a single conversation turn from a pre-built message list (gh#37). | |
| void | seed_system_prompt (const std::vector< Message > &new_messages) |
| Prepend the configured system prompt if this turn needs it. | |
| std::vector< Message > | run_drain_loop (std::string pending, const std::string &tier_override) |
| Shared drain loop for run_turn / run_turn_as (gh#99). | |
| void | seed_system_prompt_for_tier (const std::string &tier) |
| Seed a tier's system prompt on an empty conversation (gh#99). | |
| bool | prepare_next_turn (std::vector< Message > &pending) |
Pull the next queued user message into pending (gh#40). | |
| int | run_streaming (const std::string &input, TokenCallback on_token, void *user_data, int *cancel_flag, const std::string &tier="") |
| Run a streaming conversation turn (stateful). | |
| int | run_streaming (std::vector< Message > new_messages, TokenCallback on_token, void *user_data, int *cancel_flag) |
| Streaming conversation turn from a pre-built message list (gh#37). | |
| void | clear_conversation () |
| Clear conversation history. | |
| size_t | message_count () const |
| Get conversation message count. | |
| const std::vector< Message > & | get_messages () const |
| Get conversation messages (read-only). | |
| bool | queue_user_message (const std::string &message) |
| Append a user message to the mid-gen queue. | |
| size_t | user_message_queue_depth () const |
| Snapshot of the queue depth. | |
| void | clear_user_message_queue () |
| Drop all queued user messages. | |
| void | set_message_queue_capacity (int cap) |
| Set the runtime capacity of the mid-gen queue. | |
| bool | is_running () const |
| Whether a top-level run_turn is currently in progress. | |
| bool | try_begin_turn (const std::string &key) |
| Try to claim one turn for a named session (gh#144 / gh#158). | |
| bool | try_begin_turn () |
| Claim a turn for the session bound to THIS thread (gh#158). | |
| void | end_turn (const std::string &key) |
| Release a turn claimed by try_begin_turn (gh#144 / gh#158). | |
| void | end_turn () |
| Release the turn this thread claimed (gh#158). | |
| std::size_t | active_run_count () const |
| Number of runs currently in flight on this handle (gh#158). | |
| void | set_concurrent_sessions (bool enabled) |
| Allow runs on DIFFERENT session keys to proceed together. | |
| bool | concurrent_sessions () const |
| Whether per-session concurrency is enabled (gh#158). | |
| bool | interrupt_session (const std::string &key) |
| Interrupt exactly one session's run (gh#158). | |
| bool | session_interrupted (const std::string &key) const |
| Whether a named session's in-flight run carries an interrupt. | |
| std::atomic< bool > & | run_cancel_flag () |
| The cancel flag of the run executing on THIS thread (gh#158). | |
| void | set_active_session (const std::string &key) |
| Bind this turn to a caller-scoped session (gh#144, v2.12.0). | |
| std::string | active_session_key () const |
| Session whose turn is currently running. | |
| std::vector< Message > | messages_for (const std::string &key) const |
| Messages held by a named session. | |
| bool | set_session_messages (const std::string &key, std::vector< Message > messages) |
| Replace one session's conversation wholesale (gh#165, v2.13.0). | |
| std::size_t | message_count_for (const std::string &key) const |
| Message count for a named session. | |
| void | clear_conversation_for (const std::string &key) |
| Clear one session's history, keeping the session itself. | |
| bool | drop_session (const std::string &key) |
| Forget a session entirely. | |
| std::vector< std::string > | session_keys () const |
| Keys of every session the engine currently holds. | |
| void | set_queue_observer (void(*observer)(const char *, size_t, void *), void *user_data) |
| Register an observer that fires when a queued user message is consumed and seeded as the next turn. | |
| void | set_state_observer (void(*observer)(int state, void *user_data), void *user_data) |
| Register a persistent state-transition observer. | |
| ToolExecutorHooks | build_directive_hooks () |
| Build ToolExecutorHooks wired to this engine's DirectiveProcessor. | |
| void | set_workspace_prompts (const std::string &workspace, WorkspacePrompts prompts) |
| Register (or replace) one workspace's assembled prompts. | |
| void | clear_workspace_prompts (const std::string &workspace) |
| Forget a workspace's prompts; its sessions fall back to the handle's. | |
| void | bind_session_workspace (const std::string &session, const std::string &workspace) |
Record that session belongs to workspace. | |
| std::string | session_system_prompt (const std::string &session) const |
The untiered system prompt a fresh conversation in session would be seeded with (gh#179). | |
| void | set_tier_info (const std::string &name, const ChildContextInfo &info) |
| Store pre-resolved tier context info. | |
| bool | has_tier (const std::string &name) const |
| Whether a tier name is known (gh#99). | |
| std::vector< std::string > | get_tier_allowed_tools (const std::string &name) const |
| Return the allowed tool names registered for a tier (gh#121 regression). | |
| const std::string & | tier_system_prompt (const std::string &name) const |
| A tier's resolved system prompt (gh#98). | |
| void | set_relay_single_delegate (const std::string &name) |
| Mark a tier as relay-on-single-delegate. | |
| void | set_handoff_rules (const std::unordered_map< std::string, std::vector< std::string > > &rules) |
| Store handoff rules for tier delegation. | |
| bool | tier_requires_explicit_completion (const std::string &tier) const |
| Check if a tier requires an explicit entropic.complete / entropic.delegate tool call to conclude its turn. | |
| bool | is_delegation_cycle (const LoopContext &ctx, const std::string &target) const |
| Check whether pending delegation would close a cycle. | |
| bool | is_delegation_repeat_blocked (const LoopContext &ctx, const std::string &target) const |
| Predicate: should this delegation be blocked because the same target has just failed too many times? (gh#64) | |
| int64_t | seconds_since_last_activity () const |
| gh#35: seconds since the engine last serviced a run(). | |
| bool | fold_complete_into_assistant (LoopContext &ctx, const Message &tool_result_msg) const |
| gh#68 (v2.3.4): fold entropic.complete summary into the prior assistant message, suppressing the JSON tool-result user message that would otherwise land in history. | |
| void | defang_meta_action_envelope (Message &msg) const |
gh#88: reshape a meta-tool {"action":...} result so the model is not primed to parrot the call-shaped envelope. | |
| CompactionManager & | compaction_manager () |
| Borrowed reference to the engine's built-in CompactionManager. | |
Static Public Attributes | |
| static constexpr int | MAX_DELEGATION_DEPTH = 2 |
| Max delegation nesting depth (0=root, 1=child, 2=max). | |
Core agent execution engine.
Owns all engine subsystems: ResponseGenerator, ContextManager, CompactionManager, DirectiveProcessor. Implements the agentic loop (plan-act-observe-repeat) with proper state management and termination conditions.
| entropic::AgentEngine::AgentEngine | ( | const InferenceInterface & | inference, |
| const LoopConfig & | loop_config, | ||
| const CompactionConfig & | compaction_config | ||
| ) |
Construct an agent engine.
| inference | Inference interface (function pointers). |
| loop_config | Loop configuration. |
| compaction_config | Compaction configuration. |
| inference | Inference interface. |
| loop_config | Loop configuration. |
| compaction_config | Compaction configuration. @dg_internal |
Definition at line 136 of file engine.cpp.
| std::size_t entropic::AgentEngine::active_run_count | ( | ) | const |
Number of runs currently in flight on this handle (gh#158).
Runs currently in flight on this handle (gh#158).
Definition at line 3679 of file engine.cpp.
| std::string entropic::AgentEngine::active_session_key | ( | ) | const |
Session whose turn is currently running.
Session bound to this thread, else to the handle (gh#158).
gh#158 (v2.13.0): returns BY VALUE. The handle-wide fallback is a std::string every starting run assigns, and a caller on another thread — a host polling context, which is the whole point of the fallback — read it with no synchronization at all. A reference handed out across that write is a data race on the string itself, not a merely stale answer.
"" when idle or unkeyed. @utility A thread that bound a session gets its own answer — two concurrent runs each need one, and a single member field can hold only the last writer's. A thread that never bound one (an API call reading context, a direct engine driver in a test) falls back to the handle field, which is what keeps the legacy unkeyed accessors reading what they read in v2.12.0.
Returned BY VALUE, and the handle-wide fallback is read under session_key_mutex_: the member is a std::string that every starting run assigns, so a caller on another thread reading it unsynchronized — which is precisely what the unkeyed accessors do — was a data race on a string, not merely a stale answer.
Definition at line 3575 of file engine.cpp.
| void entropic::AgentEngine::bind_session_workspace | ( | const std::string & | session, |
| const std::string & | workspace | ||
| ) |
Record that session belongs to workspace.
Record a session's workspace (gh#179).
| session | Session key. |
| workspace | Workspace name. |
| session | Session key. |
| workspace | Workspace name. @req REQ-MCP-027 |
Definition at line 3873 of file engine.cpp.
| ToolExecutorHooks entropic::AgentEngine::build_directive_hooks | ( | ) |
Build ToolExecutorHooks wired to this engine's DirectiveProcessor.
Returns hooks with process_directives bridged to directive_processor(). Eliminates the need for facade bridge functions.
Definition at line 4504 of file engine.cpp.
|
inline |
Get mutable reference to engine callbacks.
Used by ToolExecutor which holds a reference that survives set_callbacks() reassignment (same pattern as ResponseGenerator).
| void entropic::AgentEngine::cancel_pause | ( | ) |
Cancel pause and interrupt completely.
Cancel pause and interrupt.
@req REQ-LOOP-006
Definition at line 1406 of file engine.cpp.
| void entropic::AgentEngine::clear_conversation | ( | ) |
Clear conversation history.
@dg_internal
Definition at line 4228 of file engine.cpp.
Clear one session's history, keeping the session itself.
Clear one session's history, keeping the session — see header.
| key | Session key. @req REQ-LOOP-001 |
| key | Session key. @dg_internal |
Definition at line 4290 of file engine.cpp.
| void entropic::AgentEngine::clear_user_message_queue | ( | ) |
Drop all queued user messages.
Drop all queued messages atomically.
@threadsafety Thread-safe.
@dg_internal
Definition at line 4417 of file engine.cpp.
Forget a workspace's prompts; its sessions fall back to the handle's.
Forget a workspace's prompts (gh#179).
| workspace | Workspace name. |
| workspace | Workspace name. @req REQ-MCP-027 |
Definition at line 3859 of file engine.cpp.
|
inline |
Borrowed reference to the engine's built-in CompactionManager.
gh#76 (v2.3.27): the facade-level CompactorRegistry borrows this reference at construction so consumer-registered compactors can fall back to the built-in default. Lifetime: the CompactionManager outlives the registry because both are owned by the engine handle (registry is destroyed in entropic_destroy before the engine).
@utility
| bool entropic::AgentEngine::concurrent_sessions | ( | ) | const |
Whether per-session concurrency is enabled (gh#158).
Definition at line 3703 of file engine.cpp.
| std::pair< int, int > entropic::AgentEngine::context_usage | ( | const std::vector< Message > & | messages | ) | const |
Get context usage for a message list.
Get context usage.
| messages | Message list. |
| messages | Message list. |
Definition at line 1419 of file engine.cpp.
gh#88: reshape a meta-tool {"action":...} result so the model is not primed to parrot the call-shaped envelope.
gh#88 de-fang logic — see header.
delegate / pipeline (and peers) return their result as {"action":"x",...} JSON. Pushed verbatim into context, the model echoes that shape as its next "tool call" — which common_chat (PEG_GEMMA4) does not parse, so the call no-ops and the loop spirals to the iteration cap. The typed directive is already built by ToolExecutor::build_directive (target/task copied into the struct) before this runs, so the model-facing content can be replaced with a non-call prose status line without affecting dispatch. entropic.complete is de-fanged earlier by the fold above.
Public so unit tests can exercise the transform without spinning the full engine loop.
| msg | Tool-result message; content reshaped in place when it is an entropic.* meta-tool action envelope. @utility |
@req REQ-LOOP-007
Definition at line 1813 of file engine.cpp.
| AgentEngine::DelegationCallbacks entropic::AgentEngine::delegation_callbacks_snapshot | ( | ) | const |
Atomically snapshot the registered delegation callbacks.
Hot path is execute_pending_delegation / execute_pending_pipeline: they grab the triple under the mutex once and pass it forward to the per-call DelegationManager. Prevents a torn read where the consumer reassigns the callbacks mid-delegation. (Hardening landed alongside the 2.1.5 verification pass.)
Definition at line 258 of file engine.cpp.
|
inline |
Forget a session entirely.
Forget a session entirely — see header.
The default session ("") is cleared rather than erased, so the legacy reference-returning accessors stay total.
| key | Session key. |
| key | Session key. |
Definition at line 4303 of file engine.cpp.
| void entropic::AgentEngine::end_turn | ( | ) |
Release the turn this thread claimed (gh#158).
Release the turn this thread claimed — see header (gh#158).
Releases by the key recorded at claim time, so a caller that claimed "A" cannot accidentally release "" — which is what an unkeyed release would have done for every pre-gh#158 call site.
@req REQ-API-009
@dg_internal
Definition at line 3666 of file engine.cpp.
Release a turn claimed by try_begin_turn (gh#144 / gh#158).
Release a turn claimed for a named session — see header.
Only the caller whose try_begin_turn returned true may call this.
| key | Session key that was claimed. @req REQ-API-009 |
| key | Session key that was claimed. @dg_internal |
Definition at line 3646 of file engine.cpp.
| bool entropic::AgentEngine::fold_complete_into_assistant | ( | LoopContext & | ctx, |
| const Message & | tool_result_msg | ||
| ) | const |
gh#68 (v2.3.4): fold entropic.complete summary into the prior assistant message, suppressing the JSON tool-result user message that would otherwise land in history.
gh#68 fold logic — see header.
Returns true when the message was folded (caller should NOT push it). Returns false when the message should be pushed as-is.
Conservative — only folds when ALL of:
msg.metadata["tool_name"] == "entropic.complete"ctx.messages.back() exists and has role == "assistant"content (typically the post-strip body when the model emitted only a tool_call)ctx.metadata["explicit_completion_summary"] is populated (set by dir_complete before this runs)If the model also emitted prose around the tool_call, the assistant body is non-empty and we leave both messages alone to avoid silently overwriting legitimate text.
Public so unit tests can exercise the predicate without spinning the full engine loop + mocking the tool executor.
@utility
Definition at line 1176 of file engine.cpp.
Get conversation messages (read-only).
Get conversation messages.
TOTAL over keys since gh#158 (v2.13.0) — see message_count(). An unknown active session yields an empty vector rather than throwing.
Definition at line 4365 of file engine.cpp.
| std::vector< std::string > entropic::AgentEngine::get_tier_allowed_tools | ( | const std::string & | name | ) | const |
Return the allowed tool names registered for a tier (gh#121 regression).
Return allowed tool names for a tier (gh#121 regression test hook).
Exposed so facade-level tests can verify that populate_tier_info captured the correct allowed_tools list after cache_tier_allowed_tools filled h->tier_allowed_tools. Returns empty when the tier is unknown or when no allowed_tools were registered.
| name | Tier name. |
| name | Tier name. |
Definition at line 4552 of file engine.cpp.
Whether a tier name is known (gh#99).
Backs entropic_run_as's unknown-tier validation. True once the tier has resolved context info (set_tier_info ran for it at configure time).
| name | Tier name. |
| name | Tier name. |
Definition at line 4540 of file engine.cpp.
| void entropic::AgentEngine::interrupt | ( | ) |
Interrupt the running loop (thread-safe).
Interrupt the running loop.
Callable from any thread and polled per-token on the generation path, so interrupt() runs many times for a single Ctrl+C. Log only on the 0→1 transition to avoid flooding the session log. (P1-4, 2.0.6-rc16)
@req REQ-LOOP-006
Definition at line 1292 of file engine.cpp.
Interrupt exactly one session's run (gh#158).
Interrupt exactly one session's run — see header (gh#158).
interrupt() means "every run on this handle" and keeps that meaning. This means "that one", and deliberately does NOT fire the external transport latch: ServerManager::interrupt_external_tools() trips EVERY transport at once, so using it here would abort another session's in-flight MCP call — the gh#150 failure mode, re-introduced through a different door. The interrupted run's own tool call still aborts, because the run publishes its cancel token to its own thread (RunCancelScope) and the transport polls it.
| key | Session whose run to interrupt. No-op when it is not running. |
| key | Session whose run to interrupt. |
Definition at line 3728 of file engine.cpp.
| bool entropic::AgentEngine::is_delegation_cycle | ( | const LoopContext & | ctx, |
| const std::string & | target | ||
| ) | const |
Check whether pending delegation would close a cycle.
Detect delegation cycles via ancestor chain check.
Exposed for unit tests. (P1-9, 2.0.6-rc16)
| ctx | Loop context (ancestor chain + locked tier). |
| target | Proposed delegation target tier. |
Targets already present in delegation_ancestor_tiers or matching the active locked_tier would re-enter an ancestor loop, which the depth cap only catches after repeated waste. (P1-9, 2.0.6-rc16)
| ctx | Loop context. |
| target | Pending delegation target tier name. |
Definition at line 1145 of file engine.cpp.
| bool entropic::AgentEngine::is_delegation_repeat_blocked | ( | const LoopContext & | ctx, |
| const std::string & | target | ||
| ) | const |
Predicate: should this delegation be blocked because the same target has just failed too many times? (gh#64)
gh#64: predicate for the consecutive-failure cap.
Returns true when target matches ctx.last_failed_delegation_target and ctx.consecutive_failed_delegations >= loop_config_.max_consecutive_failed_delegations. Exposed so tests can exercise the guard without spinning a full child loop.
| ctx | Active loop context. |
| target | Proposed delegation target tier. |
See header.
Definition at line 1161 of file engine.cpp.
|
inline |
Whether a top-level run_turn is currently in progress.
Used by the facade to reject entropic_queue_user_message with ENTROPIC_ERROR_INVALID_STATE when there is no in-flight turn to "queue behind." Thread-safe (atomic load).
| std::vector< std::string > entropic::AgentEngine::isolation_unsafe_tools | ( | const LoopContext & | ctx, |
| const std::string & | target_tier | ||
| ) |
Child-visible external tools that break the isolation claim.
External tools a sandboxed child could write through (gh#160).
Empty when isolation is off (nothing is being claimed), when no resolver is wired, or when every reachable external tool declares readOnlyHint: true.
| ctx | Parent loop context (supplies the session key). |
| target_tier | Tier the delegation targets. |
| ctx | Parent loop context (session key). |
| target_tier | Tier the delegation targets. |
Definition at line 3459 of file engine.cpp.
| LoopMetrics entropic::AgentEngine::last_loop_metrics | ( | ) | const |
Get metrics from the most recent completed run.
Metrics from the most recent completed run — see header (gh#158).
Returns a copy of the LoopMetrics snapped at the end of the last call to run() or run_turn(). Zero-initialized before any run has completed. (P2-15)
gh#158 (v2.13.0): the copy is taken under metrics_mutex_. "Returns a
copy" was never sufficient on its own — LoopMetrics is a multi-field struct, so an unlocked copy taken while a finishing run assigns it reads a TORN snapshot (new iterations, old tokens_used). Under per-handle serialization that write could not overlap a read from the consumer's thread often enough to matter; with keyed runs it can.
last_metrics_, taken under metrics_mutex_. @utility Definition at line 581 of file engine.cpp.
|
inline |
| size_t entropic::AgentEngine::message_count | ( | ) | const |
Get conversation message count.
TOTAL over keys since gh#158 (v2.13.0): an active session key that is not in the map answers 0. It used to .at(), and both this and get_messages() are reached from the C ABI, where an escaping std::out_of_range is a std::terminate.
TOTAL over keys (gh#158): an active key that is not in the map answers 0 rather than throwing. .at() here reached the C ABI through entropic_context_count, where an escaping std::out_of_range is a std::terminate — the host dies because it asked how long a conversation was. Two ordinary sequences produce an absent key: dropping the session that is still the active one, and a concurrent run publishing its key (see set_active_session).
Definition at line 4248 of file engine.cpp.
| std::size_t entropic::AgentEngine::message_count_for | ( | const std::string & | key | ) | const |
Message count for a named session.
Message count for a named session — see header.
| key | Session key. |
| key | Session key. |
Definition at line 4278 of file engine.cpp.
Messages held by a named session.
Messages held by a named session — see header.
Returns BY VALUE, unlike the legacy get_messages(). A keyed entry can be erased by drop_session, and handing out a reference into an erasable node is a use-after-free waiting for a later refactor. The copy is a few thousand short strings on a path that runs once per turn, against a turn measured in seconds.
| key | Session key. |
| key | Session key. |
Definition at line 4264 of file engine.cpp.
| void entropic::AgentEngine::pause | ( | ) |
Pause generation (thread-safe).
Pause generation.
@req REQ-LOOP-006
Definition at line 1396 of file engine.cpp.
| std::unordered_map< std::string, LoopMetrics > entropic::AgentEngine::per_tier_metrics | ( | ) | const |
Per-tier aggregated metrics since engine start.
Per-tier aggregated metrics — see header (gh#158).
Keys are tier names ("lead", "eng", etc.). Values accumulate iterations/tool_calls/tokens_used/errors and sum duration_ms across every run_loop entered with that locked_tier. Empty map before any run. (P2-15 follow-up, 2.0.6-rc16.2)
gh#158 (v2.13.0): copied under metrics_mutex_. This one was the sharper of the two — entropic_metrics_json copied the map while a concurrent run did per_tier_metrics_[tier], and an insert that rehashes relocates every bucket under the copy's iterators. Not a torn number: undefined behaviour.
metrics_mutex_. @utility Definition at line 593 of file engine.cpp.
Pull the next queued user message into pending (gh#40).
Extracted from run_turn's drain loop. Pops one queued message, fires ON_QUEUE_CONSUMED, and replaces pending with it.
| pending | Out: cleared and set to the next user turn. |
| pending | Out: cleared and set to the next user turn. |
Definition at line 4024 of file engine.cpp.
Append a user message to the mid-gen queue.
Enqueue a user message subject to the configured cap.
Bounded FIFO. Enforces LoopConfig::message_queue_capacity. Drained between top-level run_turn invocations from inside run_turn itself — never at child-delegation boundaries.
| message | User input to enqueue. |
@dg_internal
Definition at line 4388 of file engine.cpp.
| void entropic::AgentEngine::reset_interrupt | ( | ) |
Reset interrupt flag for next run.
Reset interrupt flag.
@req REQ-LOOP-006
Definition at line 1373 of file engine.cpp.
| std::filesystem::path entropic::AgentEngine::resolve_session_root | ( | const std::string & | session_key | ) |
Resolve the root a session's tools operate in (gh#160).
THE seam: sandbox roots, sandbox restore targets and (gh#166) workspace roots all come from here. Falls back to get_repo_dir() when the facade has not injected a resolver — which is what every unit test that builds a bare AgentEngine gets.
| session_key | Caller-scoped session key ("" = default). |
| session_key | Caller-scoped session key. |
Definition at line 3422 of file engine.cpp.
| std::vector< Message > entropic::AgentEngine::run | ( | std::vector< Message > | messages, |
| const std::string & | tier_override = "" |
||
| ) |
Run the engine on a set of messages.
Run the engine on initial messages.
| messages | Initial messages (system + user). |
| tier_override | gh#99: if non-empty, lock this run to the named tier (skips routing) so its grammar/samplers apply; empty routes. |
| messages | System + user messages. |
| tier_override | gh#99: if non-empty, lock the run to this tier (lock_tier_if_needed honors a pre-set locked_tier and skips routing). |
Definition at line 471 of file engine.cpp.
| std::atomic< bool > & entropic::AgentEngine::run_cancel_flag | ( | ) |
The cancel flag of the run executing on THIS thread (gh#158).
The cancel flag of this thread's run — see header (gh#158).
Handed to paths that take a std::atomic<bool>& cancel token — entropic_run_batch is the one that had a LOCAL flag nobody could ever set, which is why it was uninterruptible.
Falls back to the handle-wide interrupt flag when no run is claimed on this thread, so the reference is always valid.
Definition at line 3764 of file engine.cpp.
| std::vector< Message > entropic::AgentEngine::run_drain_loop | ( | std::string | pending, |
| const std::string & | tier_override | ||
| ) |
Shared drain loop for run_turn / run_turn_as (gh#99).
Appends pending as a user turn, runs the agentic loop under tier_override ("" = route), then drains any mid-generation queued user messages as further turns. Extracted so both entry points stay under the SLOC gate.
| pending | First user turn for this call. |
| tier_override | Tier to lock the run to ("" = route). |
| pending | First user turn for this call. |
| tier_override | Tier to lock the run to ("" = route). |
Definition at line 3954 of file engine.cpp.
| void entropic::AgentEngine::run_loop | ( | LoopContext & | ctx, |
| bool | inherit_interrupt = false |
||
| ) |
Run the engine loop on a pre-built context.
Used by DelegationManager for child loops. Public so the delegation manager (same .so) can invoke it.
gh#81 (v2.4.3): inherit_interrupt controls whether the pre-existing interrupt flag is cleared at entry. Top-level turns clear it (a fresh turn starts un-interrupted). Delegation child loops pass inherit_interrupt=true so a parent interrupt raised before/at dispatch is NOT cleared — "stop the engine" must stop children too, not reset on each nested loop.
| ctx | Loop context to execute. |
| inherit_interrupt | When true, do not reset the interrupt flag at entry (child loops inherit the parent's state). |
| ctx | Loop context to execute. |
| inherit_interrupt | When true, do not reset the interrupt flag. @req REQ-LOOP-001 @req REQ-LOOP-006 @req REQ-COMPACT-002 @req REQ-IDEN-001 |
Definition at line 408 of file engine.cpp.
| int entropic::AgentEngine::run_streaming | ( | const std::string & | input, |
| TokenCallback | on_token, | ||
| void * | user_data, | ||
| int * | cancel_flag, | ||
| const std::string & | tier = "" |
||
| ) |
Run a streaming conversation turn (stateful).
Same as run_turn but with streaming token output. Owns the StreamThinkFilter, cancel polling, and session logger wiring.
| input | User input string. |
| on_token | Consumer token callback (receives filtered UTF-8). |
| user_data | Consumer callback context. |
| cancel_flag | Polled per-token, nullable. A set flag stops THIS run only (v2.14.0, gh#205), never other sessions' runs. |
| tier | Tier or identity to lock this turn to, with the semantics of run_turn_as(); "" (the default) routes as usual. |
| input | User input. |
| on_token | Consumer callback (filtered, UTF-8 aligned). |
| user_data | Consumer context. |
| cancel_flag | Polled per-token, nullable. |
| tier | Tier or identity to lock this turn to; "" routes as usual (gh#205, v2.14.0). |
Definition at line 4119 of file engine.cpp.
| int entropic::AgentEngine::run_streaming | ( | std::vector< Message > | new_messages, |
| TokenCallback | on_token, | ||
| void * | user_data, | ||
| int * | cancel_flag | ||
| ) |
Streaming conversation turn from a pre-built message list (gh#37).
Multimodal-aware streaming run_turn overload (gh#37, v2.1.8).
Multimodal-aware streaming overload. Same content_parts preservation semantics as run_turn(vector<Message>), with token callback wiring identical to the single-string streaming variant.
| new_messages | Messages to add this turn. |
| on_token | Consumer token callback (filtered UTF-8). |
| user_data | Consumer callback context. |
| cancel_flag | Polled per-token, nullable. |
Mirrors the single-string streaming variant — same stream filter, cancel polling, session logger wiring — but consumes a pre-built message list with content_parts preserved.
| new_messages | Messages to add this turn. |
| on_token | Filtered token callback. |
| user_data | Consumer context. |
| cancel_flag | Per-token cancel poll, nullable. |
Definition at line 4189 of file engine.cpp.
Run a single conversation turn (stateful).
Manages conversation history internally. Appends user message, runs the agentic loop, appends result messages.
| input | User input string. |
gh#40 (v2.1.10): after the agent loop reaches top-level COMPLETE, drains any messages enqueued mid-generation via queue_user_message as additional turns under the same call. gh#99 (v2.8.0): the drain loop is shared with run_turn_as via run_drain_loop.
| input | User input string. |
Definition at line 3782 of file engine.cpp.
Run a single conversation turn from a pre-built message list (gh#37).
Run a stateful turn, draining any queued user messages (gh#40).
Multimodal-aware overload. Each message in new_messages is appended to the engine's conversation history with its content_parts preserved (no string flattening). The agentic loop runs over the full conversation; replies are appended to history and returned.
If the conversation is currently empty AND none of new_messages carries role == "system", the engine prepends its configured system_prompt_ first — matching the single-string overload's behavior.
| new_messages | Messages to add this turn (typically one user message; may include a system message on first turn). |
| new_messages | Messages to add this turn. |
Definition at line 4043 of file engine.cpp.
| std::vector< Message > entropic::AgentEngine::run_turn_as | ( | const std::string & | tier, |
| const std::string & | input | ||
| ) |
Run a single turn under a named tier's grammar/identity (gh#99).
Run one turn under a named tier's grammar/identity (gh#99).
Per-call tier selection on the shared resident model: seeds the tier's system prompt (from tier_info_) and locks the run to tier so its grammar + samplers apply — no 2nd model load, no reconfigure. Mirrors the delegation precedent (a child LoopContext with locked_tier + the tier's system prompt), scoped to one top-level call.
| tier | Tier name to run this call under. |
| input | User input string. |
The tier's grammar + samplers apply to THIS call (via the tier_override that pre-locks the tier, skipping routing). The tier's system prompt is seeded only when the conversation is empty (the first call on a fresh handle) — on a stateful handle that interleaves tiers, later calls switch grammar per call but keep the existing system prompt + accumulated history. For isolated per-kind runs (e.g. distinct game-agent identities), clear context between calls or use a fresh handle.
| tier | Tier to lock this call to. |
| input | User input string. |
Definition at line 3826 of file engine.cpp.
| SandboxManager * entropic::AgentEngine::sandbox_for_session | ( | const std::string & | session_key | ) |
Sandbox manager for a session, or nullptr when isolation is off (gh#160).
Sandbox manager for a session, or nullptr when isolation is off.
Public for the same reason is_delegation_cycle is: it is the observable decision point of the isolation wiring, and a test that cannot see it can only assert on a real model run.
| session_key | Session the delegation belongs to. |
delegation.isolation is none or no root resolves. @dg_internal | session_key | Session the delegation belongs to. |
Definition at line 3443 of file engine.cpp.
| int64_t entropic::AgentEngine::seconds_since_last_activity | ( | ) | const |
gh#35: seconds since the engine last serviced a run().
gh#35: idle accessor.
Updated at the entry of every run()/run_turn() call. Hosts that want an idle-exit policy poll this and tear down the engine when the value exceeds their threshold. Returned as int64 (epoch seconds delta) so consumers can compare against any unit.
See header. @utility
Definition at line 1196 of file engine.cpp.
Prepend the configured system prompt if this turn needs it.
Multimodal-aware run_turn overload (gh#37, v2.1.8).
Extracted from run_turn to keep it knots-clean. Seeds conversation_ with system_prompt_ only when the conversation is empty and the caller didn't supply its own system message.
| new_messages | The messages the caller is adding this turn. @dg_internal |
Takes a pre-built list of messages and preserves their content_parts end-to-end (no string flattening). Each input message is appended verbatim to the engine's conversation history before the agent loop runs. If the conversation is empty and the caller did not supply a system message, the engine's configured system_prompt_ is prepended first — matching the single-string overload's first-turn behavior.
| new_messages | Messages to add this turn. |
Prepend the configured system prompt if this turn needs it.
| new_messages | The messages the caller is adding this turn. @dg_internal |
Definition at line 4000 of file engine.cpp.
Seed a tier's system prompt on an empty conversation (gh#99).
Pushes tier_info_[tier].system_prompt as the system message when the conversation is empty; falls back to the global system_prompt_ when the tier carries no info.
| tier | Tier whose system prompt to seed. @dg_internal |
Precedence: the session's workspace prompt for the tier (gh#179, v2.14.0), then tier_info_[tier].system_prompt, then the session's untiered prompt. No-op once the conversation has started — like run_turn's first-turn seeding, the system prompt is NOT re-seeded mid-session when a later run_turn_as names a different tier (the grammar/samplers still switch; only the prompt persists). See run_turn_as.
| tier | Tier whose system prompt to seed. @req REQ-IDEN-001 |
Definition at line 3930 of file engine.cpp.
Whether a named session's in-flight run carries an interrupt.
Whether a session's in-flight run carries an interrupt (gh#158).
| key | Session key. |
| key | Session key. |
Definition at line 3751 of file engine.cpp.
| std::vector< std::string > entropic::AgentEngine::session_keys | ( | ) | const |
Keys of every session the engine currently holds.
Keys of every session the engine holds — see header.
Definition at line 4318 of file engine.cpp.
| std::string entropic::AgentEngine::session_system_prompt | ( | const std::string & | session | ) | const |
The untiered system prompt a fresh conversation in session would be seeded with (gh#179).
The untiered prompt a fresh conversation in session gets (gh#179).
| session | Session key. |
| session | Session key. |
Definition at line 3911 of file engine.cpp.
Bind this turn to a caller-scoped session (gh#144, v2.12.0).
Bind this turn to a caller-scoped session — see header.
"" is the default session and reproduces pre-2.12.0 behaviour exactly. The key is OPAQUE to the engine — a consumer picks whatever identifies a caller for it (a canonical repository path, a hash), which is why two callers may deliberately share one by using the same string.
Distinct from LoopContext::conversation_id, which is a storage FK minted fresh per run() and is neither caller-supplied nor stable, and from the per-handle log scope. One word, one meaning.
gh#158 (v2.13.0): the binding is published to the CALLING THREAD as well as to the handle. Two concurrent runs each need their own answer to "which session am I", and a single member field can only hold one. The member remains the answer for a thread that never bound a session, which is what keeps the legacy unkeyed accessors behaving as they did.
| key | Session key for the turn about to run. @req REQ-LOOP-001 |
The conversation entry is created BEFORE the key is published, and that order is load-bearing. Publishing first left a window in which another thread's unkeyed accessor resolved a key that was not yet in conversations_; both of those accessors then indexed the map with .at() and threw std::out_of_range out of a C entry point, aborting the host. The accessors are total now as well, so this ordering is the belt to their braces rather than the only guard.
| key | Session key for the turn about to run. @dg_internal |
Definition at line 3596 of file engine.cpp.
| void entropic::AgentEngine::set_callbacks | ( | const EngineCallbacks & | callbacks | ) |
Set callback functions for loop events.
| callbacks | Callback configuration. |
| callbacks | Callback configuration. @dg_internal |
Definition at line 167 of file engine.cpp.
Allow runs on DIFFERENT session keys to proceed together.
Allow distinct session keys to run together — see header.
docs/architecture-cpp.md, and it is COMPLETE — which is the only reason the default moved. Passing false restores v2.12.0 semantics exactly (a second run on any key is refused), so a consumer who hits a concurrency defect in the field has a one-line escape hatch instead of a version pin.Config key: concurrent_sessions: false.
| enabled | true to allow concurrent distinct-key runs. @req REQ-LOOP-009 |
| enabled | true to allow concurrent distinct-key runs. @dg_internal |
Definition at line 3690 of file engine.cpp.
| void entropic::AgentEngine::set_delegation_callbacks | ( | ent_decision_t(*)(const ent_delegation_request_t *, void *) | on_start, |
| ent_decision_t(*)(const ent_delegation_result_t *, void *) | on_complete, | ||
| void * | user_data | ||
| ) |
Register delegation start/complete callbacks (gh#29, v2.1.5).
Replaces the pre-2.1.5 silent auto-merge-to-parent behavior. The engine stores these C-style function pointers and forwards them into every DelegationManager it constructs (one per pending delegation or pipeline). Null callbacks are honored: on_start null = always ACCEPT; on_complete null = default-deny (write patch to ~/.entropic/sandbox/<session>/pending/<id>.patch).
| on_start | Pre-delegation gate (nullable clears). |
| on_complete | Post-delegation result (nullable clears). |
| user_data | Forwarded to both callbacks. |
| on_start | Pre-delegation gate (nullable). |
| on_complete | Post-delegation result (nullable). |
| user_data | Forwarded to both callbacks. @req REQ-DELEG-002 |
Definition at line 241 of file engine.cpp.
| void entropic::AgentEngine::set_dir_swap | ( | ScopedSandbox::SwapDirFn | swap_fn, |
| void * | user_data | ||
| ) |
Install the directory-swap callback used by sandboxing.
Install the tool-directory swap callback (gh#160).
gh#160: DelegationManager::set_dir_swap existed from v2.1.5 and had NO production caller, so every ScopedSandbox took the non-sandboxed branch and children wrote straight into the user's tree. The engine now holds the callback and hands it to every DelegationManager it builds.
| swap_fn | Swap callback (nullptr disables sandbox entry). |
| user_data | Forwarded to the callback. |
| swap_fn | Swap callback (nullptr disables sandbox entry). |
| user_data | Forwarded to the callback. @dg_internal |
Definition at line 3389 of file engine.cpp.
| void entropic::AgentEngine::set_external_interrupt | ( | void(*)(void *user_data) | cb, |
| void * | user_data | ||
| ) |
Register a callback invoked alongside interrupt().
Register external transport interrupt callback.
Used to propagate Ctrl+C into external MCP transports so in-flight tool calls do not run to completion. Facade wires this to ServerManager::interrupt_external_tools(). (P1-10, 2.0.6-rc16)
| cb | Callback (nullable). |
| user_data | Forwarded to cb. |
Facade wires this to ServerManager::interrupt_external_tools so AgentEngine::interrupt() unwinds tool dispatches within ~100ms. (P1-10, 2.0.6-rc16)
| cb | Callback (nullable). |
| user_data | Forwarded to cb. @req REQ-LOOP-006 |
Definition at line 1344 of file engine.cpp.
Register the external transport interrupt-release callback.
Register external transport interrupt-release callback.
gh#150: the counterpart to set_external_interrupt(). The facade wires this to ServerManager::clear_external_tool_interrupts so reset_interrupt() releases the transports it interrupted. Without it an interrupt was permanent, because the engine cleared only its own flag.
| cb | Callback (nullable). |
| user_data | Forwarded to cb. @req REQ-LOOP-006 |
Facade wires this to ServerManager::clear_external_tool_interrupts so AgentEngine::reset_interrupt() releases what interrupt() suppressed. (gh#150)
| cb | Callback (nullable). |
| user_data | Forwarded to cb. @req REQ-LOOP-006 |
Definition at line 1362 of file engine.cpp.
| void entropic::AgentEngine::set_handoff_rules | ( | const std::unordered_map< std::string, std::vector< std::string > > & | rules | ) |
Store handoff rules for tier delegation.
Store handoff rules.
| rules | Map of source tier → valid target tiers. |
| rules | Source tier → valid targets. @req REQ-IDEN-003 @req REQ-IDEN-001 |
Definition at line 4590 of file engine.cpp.
| void entropic::AgentEngine::set_hooks | ( | const HookInterface & | hooks | ) |
Set the hook dispatch interface.
| hooks | Hook dispatch interface (wired by facade). |
| hooks | Hook dispatch interface. @req REQ-HOOK-002 |
Definition at line 210 of file engine.cpp.
Set the runtime capacity of the mid-gen queue.
Update the runtime cap (in-place on LoopConfig).
If cap is less than the current depth, excess pending messages are kept (no truncation) but no new enqueues succeed until the queue drains below the new cap. cap of 0 disables enqueue while leaving the queue otherwise functional.
| cap | New capacity. @threadsafety Thread-safe. |
@dg_internal
Definition at line 4431 of file engine.cpp.
Set the configured project directory (gh#31, v2.1.6).
Store the project_dir resolved by entropic_configure_dir.
The facade calls this from entropic_configure_dir after the layered config loader has resolved the project root. get_repo_dir() uses this value in preference to std::filesystem::current_path(), so consumers whose launcher cwd differs from the target project (the common case for wrapper CLIs and IDE plugins) still snapshot the right tree into the sandbox.
Pre-2.1.6 the engine used CWD unconditionally, silently ignoring the project_dir argument to entropic_configure_dir. Setting an empty path resets the override so get_repo_dir() falls back to CWD (preserves the no-configure-dir caller's behavior).
| project_dir | Project root (empty resets to CWD fallback). @threadsafety Serialized per-handle via the facade's api_mutex. |
gh#31 (v2.1.6). See engine.h for rationale. Resets the cache so a subsequent get_repo_dir() call picks up the new value even if a previous lookup already settled on the CWD fallback.
| project_dir | Project root (empty resets to CWD fallback). @dg_internal |
Definition at line 3136 of file engine.cpp.
| void entropic::AgentEngine::set_queue_observer | ( | void(*)(const char *, size_t, void *) | observer, |
| void * | user_data | ||
| ) |
Register an observer that fires when a queued user message is consumed and seeded as the next turn.
Persistent slot setter; survives set_callbacks() shuffles.
Persistent across set_callbacks() reassignments — the streaming entry points overwrite the EngineCallbacks struct per-call, so the queue observer needs a dedicated slot to survive both streaming and non-streaming runs.
| observer | Callback (consumed_text, remaining_depth, ud). Pass nullptr to clear. |
| user_data | Forwarded to observer. @threadsafety Thread-safe. |
@dg_internal
Definition at line 4470 of file engine.cpp.
Mark a tier as relay-on-single-delegate.
When this tier is the active (lead) tier and exactly one delegate completes successfully, the delegate's summary is used as the final output without lead re-generating. Avoids redundant re-synthesis of already user-ready delegate responses.
| name | Tier name (typically "lead"). |
| name | Tier name. @req REQ-DELEG-003 |
Definition at line 4579 of file engine.cpp.
| void entropic::AgentEngine::set_session_logger | ( | SessionLogger * | log | ) |
Set session logger for model transcript logging.
| logger | Non-owning pointer (nullable). Must outlive engine. |
| log | Non-owning pointer (nullable). @dg_internal |
Definition at line 3516 of file engine.cpp.
| bool entropic::AgentEngine::set_session_messages | ( | const std::string & | key, |
| std::vector< Message > | messages | ||
| ) |
Replace one session's conversation wholesale (gh#165, v2.13.0).
Replace one session's conversation wholesale (gh#165) — see header.
The write counterpart entropic_session_context_get never had, so a session could be read out but not restored: a host that stopped the engine to free VRAM lost every conversation, and the only way to put messages back — entropic_run_session — RUNS a turn per message, re-executing the whole agentic loop including tool calls.
Refuses the session that is CURRENTLY RUNNING. Every other session stays mutable mid-run: the restriction is about the conversation this turn is appending to, not about the handle being busy.
| key | Session key; "" is the default session. |
| messages | Replacement conversation. |
Refuses the RUNNING session and only that one. "Busy handle" would be the wrong rule: the conversation a turn appends to is the one that must not be swapped under it, and every other session is inert from that turn's point of view.
| key | Session key. |
| messages | Replacement conversation. |
Definition at line 4341 of file engine.cpp.
| void entropic::AgentEngine::set_session_root_interface | ( | const SessionRootInterface & | iface | ) |
Inject the session-root / tool-reach seam (gh#160, v2.13.0).
Install the facade's session-root seam (gh#160).
The facade owns the ServerManager and therefore the only truthful answer to "which directory do this session's tools resolve against". Without this the engine snapshotted its own repo_dir while the servers worked somewhere else, and delegation patches came out empty — the gh#160 report.
| iface | Resolver callbacks (a default-constructed value clears the wiring and restores the get_repo_dir() fallback). |
| iface | Resolver callbacks. @dg_internal |
Definition at line 3376 of file engine.cpp.
| void entropic::AgentEngine::set_state_observer | ( | void(*)(int state, void *user_data) | observer, |
| void * | user_data | ||
| ) |
Register a persistent state-transition observer.
Wire the persistent state-observer slot.
The legacy path (EngineCallbacks::on_state_change) is wiped for the duration of run_streaming because that method replaces the full callback struct to install its token sink. This persistent slot survives every set_callbacks() shuffle so consumers (notably the external MCP bridge that the entropic_set_state_observer docstring names) actually see transitions during streaming runs.
Fires alongside the legacy on_state_change slot — neither supersedes the other. Pass nullptr to clear.
| observer | State-change callback. |
| user_data | Forwarded to observer. @threadsafety Thread-safe. |
Forwarded to ResponseGenerator so the PAUSED transition that ResponseGenerator emits during handle_pause also reaches the persistent slot. The legacy EngineCallbacks::on_state_change remains supported in parallel for in-tree callers (tests etc.).
@req REQ-LOOP-001
Definition at line 4488 of file engine.cpp.
| void entropic::AgentEngine::set_storage | ( | const StorageInterface & | storage | ) |
Set the storage interface for persistence.
| storage | Storage callbacks (wired by facade). Nullable — engine works without storage (in-memory only mode). |
| storage | Storage callbacks (nullable). @dg_internal |
Definition at line 199 of file engine.cpp.
| void entropic::AgentEngine::set_stream_observer | ( | TokenCallback | observer, |
| void * | user_data | ||
| ) |
Set the global stream observer.
Fires for every token from every generation path — batch entropic_run, entropic_run_streaming, and delegate child-loop generations. Persists across per-call EngineCallbacks reassignment.
| observer | Token callback (nullable clears). |
| user_data | Forwarded to observer. |
Delegates to ResponseGenerator which owns the choke point for every generation path (streaming, batch, and child-loop delegations).
| observer | Token callback (nullable). |
| user_data | Forwarded to observer. @dg_internal |
Definition at line 228 of file engine.cpp.
Set the system prompt for conversation state.
| prompt | Assembled system prompt string. |
gh#158 (v2.13.0): under prompt_mutex_. The setter runs on the API thread (which holds api_mutex) and every reader runs on a run thread (which, since gh#109, holds nothing) — so api_mutex never made this pair safe, and keyed runs add a second concurrent reader.
| prompt | Assembled system prompt. @dg_internal |
Definition at line 3491 of file engine.cpp.
| void entropic::AgentEngine::set_tier_info | ( | const std::string & | name, |
| const ChildContextInfo & | info | ||
| ) |
Store pre-resolved tier context info.
Called at configure time. The engine uses this data for delegation instead of external TierResolutionInterface callbacks.
| name | Tier name. |
| info | Pre-resolved context info (system prompt, tools, etc.). |
| name | Tier name. |
| info | Context info. @req REQ-IDEN-001 |
Definition at line 4526 of file engine.cpp.
| void entropic::AgentEngine::set_tier_resolution | ( | const TierResolutionInterface & | tier_res | ) |
Set the tier resolution interface for delegation.
Set tier resolution interface for delegation.
| tier_res | Tier resolution callbacks (wired by facade). |
| tier_res | Tier resolution callbacks. @req REQ-IDEN-001 |
Definition at line 188 of file engine.cpp.
| void entropic::AgentEngine::set_tool_executor | ( | const ToolExecutionInterface & | tool_exec | ) |
Set the tool execution interface.
| tool_exec | Tool execution interface (wired by facade). |
| tool_exec | Tool execution interface. @dg_internal |
Definition at line 177 of file engine.cpp.
| void entropic::AgentEngine::set_validation_provider | ( | char *(*)(void *) | provider, |
| void * | user_data | ||
| ) |
Register a JSON provider for the validation block in ON_COMPLETE hook context.
Register validation JSON provider for ON_COMPLETE context.
The callback returns a malloc'd JSON object describing the validator's most recent result: {ran, verdict, violations, revisions_applied} The engine copies and frees the returned buffer. NULL return or nullptr callback means no validation block is emitted. (E3, 2.0.6-rc17)
| provider | JSON builder (nullable clears). |
| user_data | Forwarded to provider. |
| provider | JSON builder callback (nullable). |
| user_data | Forwarded to provider. @req REQ-DELEG-003 |
Definition at line 270 of file engine.cpp.
| void entropic::AgentEngine::set_workspace_prompts | ( | const std::string & | workspace, |
| WorkspacePrompts | prompts | ||
| ) |
Register (or replace) one workspace's assembled prompts.
Register (or replace) one workspace's assembled prompts (gh#179).
Takes effect for every session bound to workspace whose conversation has not started; a started conversation keeps the system message it was seeded with.
| workspace | Workspace name. |
| prompts | Assembled prompts. |
| workspace | Workspace name. |
| prompts | Assembled prompts. @req REQ-MCP-027 |
Definition at line 3844 of file engine.cpp.
Check if a tier requires an explicit entropic.complete / entropic.delegate tool call to conclude its turn.
Check if a tier contractually requires explicit completion.
Exposed for unit tests. (P1-6, 2.0.6-rc16)
| tier | Tier name. |
Delegates to the TierResolutionInterface, falling back to false when no resolver is wired (preserves legacy behavior in tests that omit tier metadata).
| tier | Tier name. |
Definition at line 1124 of file engine.cpp.
| const TierResolutionInterface & entropic::AgentEngine::tier_resolution | ( | ) | const |
Get the tier resolution interface.
Definition at line 282 of file engine.cpp.
A tier's resolved system prompt (gh#98).
Backs the batch entry point, which builds each request's messages with its tier's system prompt so same-tier requests share a prompt prefix.
| name | Tier name. |
| name | Tier name. |
Definition at line 4566 of file engine.cpp.
|
inline |
Claim a turn for the session bound to THIS thread (gh#158).
The no-argument form every pre-gh#158 call site already uses. It resolves to whatever set_active_session published on this thread, so run_turn's internal "claim only if the caller has not already" probe asks about the right session rather than always about "".
try_begin_turn(key). @req REQ-API-009 Try to claim one turn for a named session (gh#144 / gh#158).
Claim one turn for a named session — see header (gh#158).
running_flag_ — deliberately NOT a mutex, because gh#109 removed api_mutex from every run entry point so a long turn could not block entropic_interrupt() from another thread. gh#158 keys the claim, which needs a map, which needs a lock — but runs_mutex_ is held only for the O(1) insert and is NEVER held across a decode, a prefill or a tool call. That is the property gh#109 actually protects; a lock held for nanoseconds does not violate it, whereas api_mutex (held for the whole turn) did.set_concurrent_sessions(false) has been called; with the kill switch thrown the guard is handle-exclusive again and v2.12.0 semantics hold byte for byte.| key | Session key to claim; "" is the default session. |
end_turn(key); false when the claim is refused, in which case the caller owns nothing and must not release. @req REQ-API-009 @req REQ-LOOP-009 | key | Session key to claim. |
Definition at line 3614 of file engine.cpp.
| size_t entropic::AgentEngine::user_message_queue_depth | ( | ) | const |
Snapshot of the queue depth.
Read queue depth under the queue mutex.
@threadsafety Thread-safe.
@dg_internal
Definition at line 4407 of file engine.cpp.