Class: Insika::Context::Providers::Prompt

Inherits:
Insika::ContextProvider show all
Defined in:
lib/insika/context/providers/prompt.rb

Overview

Absorbs SystemPrompt + SOUL.md. Identity is PINNED, priority 100 — never cut. required?: an agent without identity is a WRONG agent, not a degraded one. prompt_refs: priority 90 pinned fragments, from the PromptCatalog (catalog defaults to nil).

PER-AGENT identity, from profile.prompt_files/base_prompt only — an agent that declares neither has no identity here, and there is no deployment-wide fallback file to borrow one from. A shared fallback (a prior design: an agent without prompt_files silently inherited a wiring-level default) is exactly how a real deployment answered as the WRONG business: a copilot data agent provisioned without its own identity inherited the deployment's demo persona ("Bia, Pizzaria do Zé") byte for byte, confirmed live. An agent never wears another agent's identity — @base/system_files stay legitimate (the same generic content for every agent, never one agent's specific persona).

Constant Summary collapse

TOOL_PERSISTENCE =

Engine-owned execution discipline, appended AFTER the agent's identity. The one behavior every reference harness bakes into its base prompt (OpenClaw's "Execution Bias") and this engine was missing: a weak tool result read as final. A constant — byte-identical every turn, so prompt_caching pays ONE write on the deploy that introduces it, never per turn. Opt-out per profile (tool_persistence false), the single default-ON profile flag: the proven-good behavior is the default, the exception is the thing an operator declares.

"## Tool discipline\n" \
"- Weak or empty tool result: try again with a different approach — rephrase the " \
"query, use a synonym or broader term, drop a secondary filter — before telling " \
"the user you found nothing. Do not narrate the retries. Then conclude.\n" \
"- Tool error: read the error, fix the arguments or try another path; never " \
"repeat the exact same call.\n" \
"- A URL in a tool result (e.g. a `url` field): quote it byte-for-byte. Never " \
"construct, guess, or rewrite the domain, host, or path."

Instance Method Summary collapse

Methods inherited from Insika::ContextProvider

#enabled_for?, #id

Constructor Details

#initialize(base: "", catalog: nil, agent_files: nil, system_files: nil) ⇒ Prompt

Returns a new instance of Prompt.



39
40
41
42
43
44
# File 'lib/insika/context/providers/prompt.rb', line 39

def initialize(base: "", catalog: nil, agent_files: nil, system_files: nil)
  @base = base
  @catalog = catalog
  @agent_files = agent_files
  @system_files = system_files
end

Instance Method Details

#call(request) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/insika/context/providers/prompt.rb', line 50

def call(request)
  identity = build_identity(request.profile)
  if identity.empty?
    raise ContextError.new(
      "agent '#{request.profile&.id}' has no identity of its own (no base_prompt, " \
      "no prompt_files) — refusing to run rather than answer with no identity or " \
      "another agent's",
      provider: id
    )
  end

  fragments = [ContextFragment.build(content: identity, placement: :system,
                                     priority: Context::Priority::IDENTITY, source: id, pinned: true)]
  fragments.concat(ref_fragments(request.profile))
  fragments
end

#layerObject

identity (config/agent-file derived — already pinned).



48
# File 'lib/insika/context/providers/prompt.rb', line 48

def layer = :identity

#required?Boolean

Returns:

  • (Boolean)


46
47
# File 'lib/insika/context/providers/prompt.rb', line 46

def required? = true
# identity (config/agent-file derived — already pinned).