insika 0.3.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +296 -0
  3. data/README.md +48 -12
  4. data/bin/insika +725 -0
  5. data/bin/insika-router +87 -0
  6. data/docs/AGENTS.md +116 -406
  7. data/docs/API.md +5 -5
  8. data/docs/ARCHITECTURE.md +3 -2
  9. data/docs/ARTIFACTS.md +137 -0
  10. data/docs/BENCHMARK.md +2 -2
  11. data/docs/CHANNELS.md +14 -14
  12. data/docs/CONTEXT.md +63 -19
  13. data/docs/DEMO.md +80 -0
  14. data/docs/DEPLOY.md +87 -10
  15. data/docs/EMBEDDING.md +1 -1
  16. data/docs/EVALS.md +128 -3
  17. data/docs/FACTS.md +3 -3
  18. data/docs/HARVEST.md +5 -6
  19. data/docs/KNOWLEDGE.md +290 -0
  20. data/docs/LOADTEST.md +17 -29
  21. data/docs/MEDIA.md +128 -0
  22. data/docs/OBSERVABILITY.md +46 -12
  23. data/docs/OUTCOMES.md +137 -0
  24. data/docs/PLUGINS.md +51 -6
  25. data/docs/POLICY.md +222 -0
  26. data/docs/REFINEMENT.md +14 -9
  27. data/docs/RELEASING.md +4 -4
  28. data/docs/ROUTER.md +213 -0
  29. data/docs/RUNNING-LOCAL.md +5 -5
  30. data/docs/SCHEDULING.md +121 -0
  31. data/docs/SECURITY.md +23 -7
  32. data/docs/SKILLS.md +11 -2
  33. data/docs/SOAK.md +3 -3
  34. data/docs/TEMPLATES.md +134 -0
  35. data/docs/TOOLS.md +176 -27
  36. data/docs/WHY.md +1 -1
  37. data/docs/WORKFLOWS.md +2 -2
  38. data/docs/_includes/head_custom.html +5 -0
  39. data/docs/_includes/title.html +13 -0
  40. data/docs/_sass/color_schemes/insika.scss +32 -0
  41. data/docs/_sass/custom/custom.scss +199 -0
  42. data/docs/_sass/custom/setup.scss +26 -0
  43. data/docs/assets/img/favicon.svg +7 -0
  44. data/docs/assets/img/insika-mark.svg +7 -0
  45. data/docs/core-concepts.md +21 -0
  46. data/docs/domain.md +4 -4
  47. data/docs/improve.md +20 -0
  48. data/docs/index.md +8 -5
  49. data/docs/integrate.md +20 -0
  50. data/docs/operate.md +13 -6
  51. data/docs/prompts/ADD-TOOL.md +118 -0
  52. data/docs/prompts/DIAGNOSE-TURN.md +65 -0
  53. data/docs/prompts/GO-LIVE.md +138 -0
  54. data/docs/prompts/RUN-EXAMPLES.md +70 -0
  55. data/docs/reference.md +19 -0
  56. data/docs/ship.md +10 -2
  57. data/docs/start-here.md +18 -0
  58. data/lib/insika/agent_profile.rb +99 -17
  59. data/lib/insika/artifact_signing.rb +82 -0
  60. data/lib/insika/artifact_store.rb +160 -0
  61. data/lib/insika/channel_delivery.rb +1 -1
  62. data/lib/insika/chat_builder.rb +50 -19
  63. data/lib/insika/commands/agent_payload.rb +2 -2
  64. data/lib/insika/commands/backfill_knowledge.rb +145 -0
  65. data/lib/insika/commands/delete_artifact.rb +35 -0
  66. data/lib/insika/commands/delete_concept.rb +34 -0
  67. data/lib/insika/commands/delete_mcp.rb +6 -2
  68. data/lib/insika/commands/delete_tenant_data.rb +15 -3
  69. data/lib/insika/commands/gate_refinement.rb +1 -1
  70. data/lib/insika/commands/refresh_mcp_tools.rb +47 -0
  71. data/lib/insika/commands/restore_concept.rb +34 -0
  72. data/lib/insika/commands/seed_demo_data.rb +31 -0
  73. data/lib/insika/commands/upsert_mcp.rb +6 -3
  74. data/lib/insika/commands/write_concept.rb +57 -0
  75. data/lib/insika/compaction.rb +196 -0
  76. data/lib/insika/context/builder.rb +6 -2
  77. data/lib/insika/context/fragment.rb +4 -1
  78. data/lib/insika/context/priority.rb +8 -0
  79. data/lib/insika/context/providers/briefing.rb +53 -24
  80. data/lib/insika/context/providers/knowledge.rb +108 -0
  81. data/lib/insika/context/providers/prompt.rb +30 -24
  82. data/lib/insika/context/providers/session.rb +46 -10
  83. data/lib/insika/context_trace_store.rb +11 -1
  84. data/lib/insika/cron.rb +189 -0
  85. data/lib/insika/demo/agent_attrs.rb +43 -0
  86. data/lib/insika/demo/golden_cases.rb +81 -0
  87. data/lib/insika/demo/seeder.rb +336 -0
  88. data/lib/insika/doctor.rb +280 -17
  89. data/lib/insika/dsl/definition.rb +3 -2
  90. data/lib/insika/dsl/runtime.rb +64 -79
  91. data/lib/insika/dsl/server_boot.rb +23 -1
  92. data/lib/insika/dsl/system.rb +10 -2
  93. data/lib/insika/dsl.rb +103 -2
  94. data/lib/insika/env_schema.rb +21 -7
  95. data/lib/insika/evals/golden.rb +41 -4
  96. data/lib/insika/evals/judge.rb +47 -2
  97. data/lib/insika/evals/pairwise.rb +11 -0
  98. data/lib/insika/evals/persona.rb +98 -0
  99. data/lib/insika/evals/runner.rb +9 -0
  100. data/lib/insika/evals/simulator.rb +225 -0
  101. data/lib/insika/evals/transport.rb +84 -2
  102. data/lib/insika/event_stream.rb +10 -0
  103. data/lib/insika/executor.rb +295 -55
  104. data/lib/insika/followup_policy.rb +2 -25
  105. data/lib/insika/golden_store.rb +16 -1
  106. data/lib/insika/grounding/matcher.rb +1 -1
  107. data/lib/insika/knowledge.rb +680 -0
  108. data/lib/insika/knowledge_store.rb +140 -0
  109. data/lib/insika/loop_detector.rb +5 -34
  110. data/lib/insika/mcp_client.rb +94 -0
  111. data/lib/insika/mcp_json.rb +74 -0
  112. data/lib/insika/mcp_live_tool.rb +43 -0
  113. data/lib/insika/mcp_store.rb +98 -26
  114. data/lib/insika/mcp_tool_ingestor.rb +30 -8
  115. data/lib/insika/mcp_tool_registry.rb +100 -0
  116. data/lib/insika/media.rb +115 -31
  117. data/lib/insika/message_origin.rb +1 -1
  118. data/lib/insika/middleware.rb +9 -0
  119. data/lib/insika/onboarding.rb +17 -1
  120. data/lib/insika/outcome_store.rb +1 -1
  121. data/lib/insika/overlay_tool_registry.rb +37 -17
  122. data/lib/insika/packaging.rb +2 -2
  123. data/lib/insika/profile_source.rb +15 -1
  124. data/lib/insika/prompt_catalog.rb +10 -0
  125. data/lib/insika/retention.rb +36 -1
  126. data/lib/insika/router/app.rb +157 -0
  127. data/lib/insika/router/backend_pool.rb +98 -0
  128. data/lib/insika/router/hash_ring.rb +55 -0
  129. data/lib/insika/router/proxy_body.rb +34 -0
  130. data/lib/insika/router/session_key.rb +54 -0
  131. data/lib/insika/router.rb +18 -0
  132. data/lib/insika/schedule.rb +177 -0
  133. data/lib/insika/schedule_engine.rb +314 -0
  134. data/lib/insika/schedule_store.rb +208 -0
  135. data/lib/insika/server/app.rb +105 -15
  136. data/lib/insika/server/rack_app.rb +5 -1
  137. data/lib/insika/server/responses.rb +5 -5
  138. data/lib/insika/session_store.rb +34 -4
  139. data/lib/insika/settings_store.rb +8 -1
  140. data/lib/insika/skill_catalog.rb +12 -0
  141. data/lib/insika/soak/runner.rb +4 -4
  142. data/lib/insika/steer_injector.rb +21 -10
  143. data/lib/insika/studio/app.rb +591 -47
  144. data/lib/insika/studio/assets/dist/application.css +1 -1
  145. data/lib/insika/studio/assets/dist/application.js +21 -21
  146. data/lib/insika/studio/forms.rb +57 -5
  147. data/lib/insika/studio/nav_icons.rb +14 -1
  148. data/lib/insika/studio/views/_agent_tab_cache.erb +25 -0
  149. data/lib/insika/studio/views/_agent_tab_config.erb +514 -0
  150. data/lib/insika/studio/views/_agent_tab_history.erb +24 -0
  151. data/lib/insika/studio/views/_agent_tab_loops.erb +54 -0
  152. data/lib/insika/studio/views/_agent_tab_memory.erb +51 -0
  153. data/lib/insika/studio/views/_agent_tab_outcomes.erb +31 -0
  154. data/lib/insika/studio/views/_agent_tab_prompts.erb +108 -0
  155. data/lib/insika/studio/views/_agent_tab_skills.erb +38 -0
  156. data/lib/insika/studio/views/_agents_master.erb +44 -0
  157. data/lib/insika/studio/views/_message.erb +49 -32
  158. data/lib/insika/studio/views/agent_detail.erb +61 -820
  159. data/lib/insika/studio/views/agents.erb +70 -57
  160. data/lib/insika/studio/views/artifact.erb +23 -0
  161. data/lib/insika/studio/views/artifacts.erb +59 -0
  162. data/lib/insika/studio/views/evals.erb +2 -2
  163. data/lib/insika/studio/views/facts.erb +1 -1
  164. data/lib/insika/studio/views/funnel.erb +1 -1
  165. data/lib/insika/studio/views/home.erb +106 -67
  166. data/lib/insika/studio/views/knowledge.erb +123 -0
  167. data/lib/insika/studio/views/layout.erb +14 -11
  168. data/lib/insika/studio/views/mcp.erb +174 -80
  169. data/lib/insika/studio/views/session.erb +231 -177
  170. data/lib/insika/studio/views/settings.erb +50 -1
  171. data/lib/insika/studio/views/skills.erb +1 -1
  172. data/lib/insika/studio/views/tools.erb +24 -9
  173. data/lib/insika/telemetry/recorder.rb +49 -1
  174. data/lib/insika/templates/browser-agent/README.md +36 -0
  175. data/lib/insika/templates/browser-agent/agent.rb +49 -0
  176. data/lib/insika/templates/daily-digest/README.md +47 -0
  177. data/lib/insika/templates/daily-digest/agent.rb +77 -0
  178. data/lib/insika/templates/repo-explorer/README.md +36 -0
  179. data/lib/insika/templates/repo-explorer/agent.rb +45 -0
  180. data/lib/insika/templates/research-analyst/README.md +26 -0
  181. data/lib/insika/templates/research-analyst/agent.rb +68 -0
  182. data/lib/insika/templates/review-panel/README.md +20 -0
  183. data/lib/insika/templates/review-panel/agent.rb +50 -0
  184. data/lib/insika/templates/travel-planner/README.md +35 -0
  185. data/lib/insika/templates/travel-planner/agent.rb +87 -0
  186. data/lib/insika/templates.rb +112 -0
  187. data/lib/insika/tick.rb +24 -12
  188. data/lib/insika/timezone.rb +45 -0
  189. data/lib/insika/tool_batch.rb +67 -0
  190. data/lib/insika/tool_usage_report.rb +162 -0
  191. data/lib/insika/tools/generate_image.rb +52 -7
  192. data/lib/insika/tools/load_knowledge.rb +74 -0
  193. data/lib/insika/tools/run_persona_eval.rb +328 -0
  194. data/lib/insika/tools/save_artifact.rb +95 -0
  195. data/lib/insika/turn_budget.rb +91 -0
  196. data/lib/insika/turn_output.rb +1 -1
  197. data/lib/insika/turn_state.rb +15 -4
  198. data/lib/insika/version.rb +1 -1
  199. data/lib/insika/wiring/graph.rb +184 -12
  200. data/lib/insika/wiring/graph_chat.rb +102 -0
  201. data/lib/insika.rb +64 -0
  202. metadata +109 -5
  203. data/docs/build.md +0 -14
  204. data/docs/understand.md +0 -10
data/docs/index.md CHANGED
@@ -8,7 +8,7 @@ permalink: /
8
8
  {: .fs-9 }
9
9
 
10
10
  Your agent is the idea. Insika is what holds it up in production.
11
- {: .fs-6 .fw-300 }
11
+ {: .hero-tagline }
12
12
 
13
13
  [Build your first agent](RUNNING-LOCAL.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }
14
14
  [View on GitHub](https://github.com/guizaols/insika){: .btn .fs-5 .mb-4 .mb-md-0 }
@@ -60,9 +60,12 @@ secrets), `GET /docs` and `GET /docs/<name>.md`. Public and on by default when y
60
60
 
61
61
  ## Where to go next
62
62
 
63
- - **[Understand the idea](understand.md)** — why a runtime rather than a DIY loop, and how a turn actually runs.
64
- - **[Build an agent](build.md)** — agents, tools, skills, context, and the local loop.
65
- - **[Ship it](ship.md)** — security, confined execution, deployment.
66
- - **[Operate & prove it](operate.md)** — observability, the benchmark, load testing, evals, refinement.
63
+ - **[Start here](start-here.md)** — why a runtime, getting one running, and what a turn actually does.
64
+ - **[Core concepts](core-concepts.md)** — agents, limits, tools, skills, context, workflows.
65
+ - **[Integrate](integrate.md)** — the API, channels, media, embedding, plugins, templates.
66
+ - **[Ship it](ship.md)** — security, confined execution, deployment, scaling past one worker.
67
+ - **[Operate](operate.md)** — observability, schedules, artifacts, load and soak testing.
68
+ - **[Improve](improve.md)** — evals, refinement, outcomes, and the three learning loops.
69
+ {: .card-grid }
67
70
 
68
71
  Pre-release: APIs may still change and nothing is tagged yet. Licensed MIT.
data/docs/integrate.md ADDED
@@ -0,0 +1,20 @@
1
+ ---
2
+ title: Integrate
3
+ nav_order: 4
4
+ has_children: true
5
+ permalink: /integrate/
6
+ ---
7
+
8
+ # Integrate
9
+
10
+ How the agent connects to everything that is not the engine: the clients that
11
+ call it, the places people talk to it from, the app it may live inside, and the
12
+ code you write to extend it.
13
+
14
+ - **[The /v1 API](API.md)** — the frozen, OpenAI-Responses-compatible contract.
15
+ - **[Channels](CHANNELS.md)** — the web widget and the relay: how people actually reach the agent.
16
+ - **[Media](MEDIA.md)** — photos, voice notes and documents in; generated images out.
17
+ - **[Embedding](EMBEDDING.md)** — mounting the engine inside a Ruby app you already have.
18
+ - **[Plugins](PLUGINS.md)** — the two extension tiers, and how to pick between them.
19
+ - **[Templates](TEMPLATES.md)** — the example agents that ship in the gem, and the gallery that installs them.
20
+ {: .card-grid }
data/docs/operate.md CHANGED
@@ -1,12 +1,19 @@
1
1
  ---
2
- title: Operate & prove it
3
- nav_order: 5
2
+ title: Operate
3
+ nav_order: 6
4
4
  has_children: true
5
5
  permalink: /operate/
6
6
  ---
7
7
 
8
- # Operate & prove it
8
+ # Operate
9
9
 
10
- Turns as traces and metrics, the engine's measured overhead, how to load-test it
11
- yourself, the cases that grade an agent, and reading a live agent's own traffic back as
12
- a report of what broke.
10
+ Running it once it is live: seeing what happened, firing turns nobody sent,
11
+ handing back a report, and knowing what the box will take before it takes it.
12
+
13
+ - **[Observability](OBSERVABILITY.md)** — the event stream, and turns as OpenTelemetry traces and metrics.
14
+ - **[Schedules](SCHEDULING.md)** — recurring turns the engine fires on its own tick.
15
+ - **[Artifacts](ARTIFACTS.md)** — a report the agent can hand you a URL to.
16
+ - **[Load test](LOADTEST.md)** — end-to-end load testing, and comparing topologies before you choose one.
17
+ - **[Soak](SOAK.md)** — the long run that finds what a short one cannot.
18
+ - **[Benchmark](BENCHMARK.md)** — the engine's measured overhead, reproducible without an API key.
19
+ {: .card-grid }
@@ -0,0 +1,118 @@
1
+ ---
2
+ title: Prompt — add a tool or skill
3
+ parent: Reference
4
+ nav_order: 3
5
+ permalink: /add-tool/
6
+ layout: default
7
+ render_with_liquid: false
8
+ ---
9
+
10
+ # Add a tool, MCP server, or skill to my agent
11
+
12
+ > **You are a coding agent** (Claude Code, Codex, Cursor, …) reading this because a
13
+ > developer pasted a prompt pointing here. Treat this file as a **skill**: follow the
14
+ > steps in order and apply the RULES literally.
15
+
16
+ Your job: extend **one existing agent** with **one new capability** and prove it works
17
+ with one turn. Nothing more.
18
+
19
+ ## Step 0 — Gather context (silently)
20
+
21
+ - **Which agent?** Find its `Insika.agent { … }` block (or its pack). If the developer
22
+ has no agent yet, stop and build the minimal first agent instead — this file assumes
23
+ one exists. Do not mix onboarding with capability.
24
+ - **A provider key in the environment**; ask if none is set.
25
+ - Read [`docs/TOOLS.md`](../TOOLS.md) (also served at `GET /docs/tools.md`) and, for
26
+ skills, [`docs/SKILLS.md`](../SKILLS.md) before writing anything.
27
+
28
+ ## Step 1 — Pick the kind (RULES, not taste)
29
+
30
+ | The need | The kind | Where it lives |
31
+ |---|---|---|
32
+ | Call an external HTTP API | **data tool** (`data_tool` in the DSL block) | a row in SQLite, editable at runtime |
33
+ | Logic must run in-process | **code tool** (a Ruby class `< RubyLLM::Tool`) | the deployment image |
34
+ | Adopt a whole external MCP server | **`mcp` instance** | durable config; its tools appear tagged `mcp:<name>` |
35
+ | Teach a procedure (no data fetching) | **skill** (`skill "name", description:, instructions:`) | loads on demand via `load_skill` |
36
+
37
+ Exactly one kind. A skill is not a tool; an MCP server is not five data tools.
38
+
39
+ ## Step 2 — Build the smallest version
40
+
41
+ Data tool, via DSL (shape from
42
+ [`examples/data-tool/`](https://github.com/guizaols/insika/tree/main/examples/data-tool/)):
43
+
44
+ ```ruby
45
+ data_tool(
46
+ "name" => "convert_currency",
47
+ "description" => "Latest reference exchange rate between two currencies.",
48
+ "parameters" => {
49
+ "type" => "object",
50
+ "properties" => {
51
+ "from" => { "type" => "string", "description" => "source currency code" },
52
+ "to" => { "type" => "string", "description" => "target currency code" }
53
+ },
54
+ "required" => %w[from to]
55
+ },
56
+ "request" => { "method" => "GET",
57
+ "url" => "https://api.example.com/latest?from={{from}}&to={{to}}" },
58
+ "response" => { "extract" => "body_raw" }
59
+ )
60
+ ```
61
+
62
+ Skill, via DSL (from
63
+ [`examples/skills/`](https://github.com/guizaols/insika/tree/main/examples/skills/)):
64
+
65
+ ```ruby
66
+ skill "refunds",
67
+ description: "How to handle a refund request",
68
+ instructions: <<~MD
69
+ When a customer asks for a refund:
70
+ 1. If you don't have the order number, ask for it first.
71
+ …
72
+ MD
73
+ ```
74
+
75
+ RULES:
76
+
77
+ - `parameters` is JSON Schema (safe subset — no `oneOf`/`$ref`); it reaches the model
78
+ verbatim and arguments are checked against it at call time.
79
+ - Author the FINAL url: the HTTP client does not follow redirects, and the egress guard
80
+ cleared that host only.
81
+ - Do not add a second capability "while we're here".
82
+
83
+ ## Step 3 — Make sure it enters the tool-loop
84
+
85
+ Registered is not enough — the agent's policy allowlist decides. The DSL auto-enables
86
+ the allowlist policy, and the three-state rule applies (`nil` = all, `[]` = none,
87
+ `[names]` = exactly those; deny wins):
88
+
89
+ ```ruby
90
+ tools %w[convert_currency] # or tools_allow: [...] on the pack
91
+ ```
92
+
93
+ A code tool can never be shadowed by a data tool of the same name — pick another name
94
+ instead of fighting it.
95
+
96
+ ## Step 4 — Prove it with ONE turn
97
+
98
+ Run one `reply()` whose message forces the call ("how many BRL is 1 USD right now?").
99
+ The reply must use what the tool returned — if the model answers from imagination, the
100
+ tool did not run: re-check Step 3 before touching the prompt.
101
+
102
+ ## Step 5 — Self-check
103
+
104
+ - [ ] One agent, one new capability, one proving turn with real output.
105
+ - [ ] The tool/skill is named in the allowlist (or absence was a deliberate "all").
106
+ - [ ] No secret in any file — keys live in the environment.
107
+ - [ ] No new gem dependency was added without asking.
108
+
109
+ ## Hard constraints
110
+
111
+ - **Secrets stay in the environment.** `{{secret.*}}` resolves ONLY on the manifest
112
+ write path (`POST /v1/tools/manifest`); written via DSL or Studio it fails
113
+ registration. Tools authored outside a manifest ship literal values (masked on read).
114
+ - **The egress guard refusing a URL is a feature**, not a bug to disable globally.
115
+ Report it; open an allowlist exception deliberately.
116
+ - **Config over code**: everything above is data the DSL generates (`to_pack`). If it
117
+ seems to require reaching past the DSL, the answer is a DSL method you have not used
118
+ yet — re-read the docs first.
@@ -0,0 +1,65 @@
1
+ ---
2
+ title: Prompt — diagnose a failed turn
3
+ parent: Reference
4
+ nav_order: 4
5
+ permalink: /diagnose-turn/
6
+ layout: default
7
+ render_with_liquid: false
8
+ ---
9
+
10
+ # Diagnose a turn that failed or misbehaved
11
+
12
+ > **You are a coding agent** (Claude Code, Codex, Cursor, …) reading this because a
13
+ > developer pasted a prompt pointing here — something like *"the agent didn't answer /
14
+ > answered wrong / errored"*. Treat this file as a **skill**: investigate BEFORE
15
+ > proposing fixes, and report findings in plain language with evidence.
16
+
17
+ The engine already recorded what happened: every turn emits structured events stamped
18
+ with `task_id`/`session_id`. Your job is to read the record, not to guess.
19
+
20
+ ## Step 0 — Pin down the facts
21
+
22
+ Ask for (or find) the minimum: **agent id**, **session id** (or the customer's message
23
+ text), roughly **when**, and expected vs. actual. Reproduce once locally if cheap
24
+ (`reply()` or one `curl` against a dev instance) — never hammer production.
25
+
26
+ ## Step 1 — Read the record, in this order
27
+
28
+ 1. **`GET /v1/tasks/:id`** (or the Studio) — the terminal state:
29
+ `completed` / `failed` / `cancelled`, outcome, usage, timing. No task id? Find it
30
+ via **`GET /v1/events?session_id=…`**.
31
+ 2. **That task's events**: `task_started` → `tool_call`/`tool_result`/`data_tool_call`
32
+ … → the terminal event. A failure's reason lives there.
33
+ 3. **`GET /v1/sessions/:id`** — the transcript: what the model actually saw and said.
34
+ 4. **`bin/insika doctor`** — configuration sanity; relay its findings verbatim.
35
+
36
+ ## Step 2 — Map symptom to mechanism
37
+
38
+ | On the record | Usual suspect | Details |
39
+ |---|---|---|
40
+ | provider auth/model error | missing key or wrong model id | fails at the provider, not the engine |
41
+ | `provider_failure` then `provider_fallback` | reliability chain rotated mid-turn | [Agents](../AGENTS.md) § reliability |
42
+ | `breaker_open` + fail-fast turns | circuit open until cooldown | same |
43
+ | turn completed, customer got nothing | delivery is separate from the turn: check `channel_delivered` / `delivery_failed` | [Channels](../CHANNELS.md) |
44
+ | freshly created agent returns empty turns | persona overflows the default `context_budget` (8000) | [Context](../CONTEXT.md) |
45
+ | tool never called (or "missing") | not registered OR not allowed (`tools_allow`) | [Tools](../TOOLS.md) § troubleshooting |
46
+ | identical `tool_call` repeated, then abort | the `max_tool_repeat` loop guard | [Agents](../AGENTS.md) § limits |
47
+ | model gave up after one empty result | `tool_persistence` off (it is ON by default) | same |
48
+ | `turn_stuck` event | the agent declared it cannot proceed — escalation signal, not a bug | [Agents](../AGENTS.md) § stuck |
49
+
50
+ ## Step 3 — Report, then fix ONE thing
51
+
52
+ - Plain-language summary: **what happened → evidence (event names + ids) → root cause
53
+ → the fix you propose.**
54
+ - Apply the fix; re-run the Step 0 reproduction; show the new terminal event as proof.
55
+ - If the evidence does not fit any row above, say so and bring the raw events back —
56
+ do not force a diagnosis.
57
+
58
+ ## Hard constraints
59
+
60
+ - **Never invent event data.** If you did not read it, you cannot claim it.
61
+ - **Do not change config just to silence the symptom** without explaining the
62
+ mechanism (raising `context_budget` because the prompt is big is a fix; deleting the
63
+ guardrail that fired is not).
64
+ - **Quote ids, counts and states first; message content only when needed** for the
65
+ developer to recognize the case.
@@ -0,0 +1,138 @@
1
+ ---
2
+ title: Prompt — go live
3
+ parent: Reference
4
+ nav_order: 5
5
+ permalink: /go-live/
6
+ layout: default
7
+ render_with_liquid: false
8
+ ---
9
+
10
+ # Take this agent to production
11
+
12
+ > **You are a coding agent** (Claude Code, Codex, Cursor, …) reading this because a
13
+ > developer pasted a prompt pointing here — something like *"deploy this"* or *"take
14
+ > it to production"*. Treat this file as a **skill**: follow the steps in order and
15
+ > apply the RULES literally. Production is where shortcuts become incidents.
16
+
17
+ Your job: get **one working local setup** running as **one production instance**,
18
+ verified end to end. The authoritative reference is
19
+ [`docs/DEPLOY.md`](../DEPLOY.md) (served at `GET /docs/deploy.md`); this file is the
20
+ ordered path through it.
21
+
22
+ ## Step 0 — Gather context (silently)
23
+
24
+ - **Repo or gem?** The reference deployment is a checkout of the insika repo
25
+ (`Dockerfile` + `config.ru` + `railway.json` already in it). An adopter's own app
26
+ consumes the gem instead — then the developer's repo needs its own image; the env
27
+ contract below is identical.
28
+ - **Which platform?** Railway is the documented path. Any Docker host works; the
29
+ Kubernetes caveats are in [`docs/DEPLOY.md`](../DEPLOY.md) § Kubernetes.
30
+ - **Does it work locally?** One green `reply()` or `serve` turn first. Do not debug an
31
+ agent and a deployment at the same time.
32
+ - Read [`docs/DEPLOY.md`](../DEPLOY.md) and
33
+ [`docs/SECURITY.md`](../SECURITY.md) before writing anything.
34
+
35
+ ## Step 1 — Mint the two secrets (RULES, not taste)
36
+
37
+ Two tokens, **two different values** — the fallback of one onto the other is a dev
38
+ convenience only:
39
+
40
+ | Token | Gates | Rotating it |
41
+ |---|---|---|
42
+ | `ADMIN_TOKEN` | `/studio` login (the operator — just you) | safe, independent |
43
+ | `INSIKA_GATEWAY_TOKEN` | Bearer for `/v1/responses` + `/v1/agents` (your API consumers) | both sides together, same step |
44
+
45
+ Generate each: `ruby -rsecurerandom -e 'puts SecureRandom.hex(24)'`. Set them as
46
+ platform env vars. **Never** write either into a file, a commit, or your own output.
47
+
48
+ ## Step 2 — The non-negotiable env
49
+
50
+ - **`INSIKA_DB` on a mounted volume** (the image defaults to `/data/insika.db` —
51
+ mount a volume at `/data`). No volume = SQLite is ephemeral and recovery resumes
52
+ nothing after a redeploy.
53
+ - **`WEB_CONCURRENCY` stays `1`.** It is a contract input, not a throughput knob:
54
+ N>1 without session-sticky routing in front is a guaranteed cross-session reply
55
+ leak, and `insika doctor` errors on it on Railway. The fix, when throughput is
56
+ actually needed, is [`insika-router`](../ROUTER.md) in front — not a bigger number.
57
+ - **Provider key** (`DEEPSEEK_API_KEY` for the demo provider) — without it the engine
58
+ still boots (`/up` green) but every turn fails until it is configured.
59
+ - **`INSIKA_EGRESS_HOSTS`** = exactly the hosts your data-tools call. A backend on the
60
+ developer's machine gets a public **https tunnel** + its host in this list — never
61
+ `INSIKA_EGRESS_ALLOW_HTTP`/`_ALLOW_PRIVATE` in cloud.
62
+ - On Railway also **`RAILWAY_DEPLOYMENT_DRAINING_SECONDS=30`**: the platform default
63
+ is 0 — SIGKILL right after SIGTERM — which cancels the graceful drain entirely.
64
+
65
+ ## Step 3 — Deploy
66
+
67
+ Railway (repo path — `railway.json` already sets builder, start command, `/up`
68
+ healthcheck, restart policy):
69
+
70
+ 1. Create the project/service from the repo (builder = Dockerfile).
71
+ 2. Mount the volume at `/data`.
72
+ 3. Set the vars from Steps 1–2.
73
+ 4. Deploy; the healthcheck must go green on `/up`.
74
+
75
+ Any Docker host, same contract:
76
+
77
+ ```bash
78
+ docker build -t insika .
79
+ docker run -p 9292:9292 -v insika-data:/data \
80
+ -e DEEPSEEK_API_KEY=... -e ADMIN_TOKEN=... -e INSIKA_GATEWAY_TOKEN=... \
81
+ insika
82
+ ```
83
+
84
+ ## Step 4 — Prove it with ONE real turn
85
+
86
+ In order, each with evidence:
87
+
88
+ 1. `curl https://<host>/up` → `{"status":"ok"}`.
89
+ 2. `bin/insika doctor` against the deployed volume (or via the platform's shell) —
90
+ relay its findings verbatim; fix errors before continuing.
91
+ 3. One authenticated turn:
92
+
93
+ ```bash
94
+ curl -N https://<host>/v1/responses \
95
+ -H "Authorization: Bearer $INSIKA_GATEWAY_TOKEN" \
96
+ -H "Content-Type: application/json" \
97
+ -d '{"model":"<agent-id>","user":"go-live-check","input":"hello"}'
98
+ ```
99
+
100
+ The reply must be real model output. 401 → token mismatch (Step 1); a provider error
101
+ → key/model id (Step 2); anything else → stop and diagnose with
102
+ [`docs/prompts/DIAGNOSE-TURN.md`](DIAGNOSE-TURN.md) before touching config.
103
+
104
+ 4. Log in to `/studio` with the new `ADMIN_TOKEN` and find the go-live-check session.
105
+
106
+ ## Step 5 — Close the total-loss hole (Litestream)
107
+
108
+ A single volume is the one point of total loss. Enable continuous replication by env
109
+ (off by default, zero code): set `LITESTREAM_REPLICA_URL` + credentials per
110
+ [`docs/DEPLOY.md`](../DEPLOY.md) § Backup / DR. Then **run the restore drill** — an
111
+ untested backup does not count:
112
+
113
+ ```bash
114
+ scripts/litestream-restore-drill.sh # local proof of the mechanism, or the
115
+ # production drill in DEPLOY.md § Restore drill
116
+ ```
117
+
118
+ If the developer declines Litestream, record that as an explicit accepted risk in
119
+ your report — do not silently skip it.
120
+
121
+ ## Step 6 — Self-check
122
+
123
+ - [ ] `/up` green, `doctor` clean, one real authenticated turn with model output.
124
+ - [ ] Two distinct tokens, both only in platform env; nothing secret in git or logs.
125
+ - [ ] Volume mounted; `WEB_CONCURRENCY=1`; drain buffer set (Railway).
126
+ - [ ] Egress allowlist names only the hosts the tools actually call.
127
+ - [ ] Litestream on **and** a restore exercised — or the risk explicitly accepted.
128
+
129
+ ## Hard constraints
130
+
131
+ - **Never raise `WEB_CONCURRENCY` to "fix" throughput.** The failure it causes is a
132
+ reply delivered to the wrong customer — read
133
+ [`docs/DEPLOY.md`](../DEPLOY.md) § The process model before proposing any scaling.
134
+ - **`_ALLOW_HTTP`/`_ALLOW_PRIVATE` never in cloud.** They exist for fully-local loops.
135
+ - **The onboarding surface (`/start.md`, `/docs`) is opt-in in production**
136
+ (`INSIKA_ONBOARDING=1`) — leaving it off is the default posture, not a bug.
137
+ - **Report every deviation.** A var you had to add, a check that failed and was
138
+ worked around, a step the platform made impossible — findings, not noise.
@@ -0,0 +1,70 @@
1
+ ---
2
+ title: Prompt — run every example
3
+ parent: Reference
4
+ nav_order: 2
5
+ permalink: /run-examples/
6
+ layout: default
7
+ render_with_liquid: false
8
+ ---
9
+
10
+ # Run every example
11
+
12
+ > **You are a coding agent** (Claude Code, Codex, Cursor, …) reading this because a
13
+ > developer pasted a prompt pointing here. Treat this file as a **skill**: follow the
14
+ > steps in order and apply the RULES literally. Do not improvise beyond them.
15
+
16
+ Your job: get every runnable example under `examples/` running — one at a time — and
17
+ explain to the developer what each one demonstrates. The authoritative list (and the
18
+ one-line capability per example) is
19
+ [`examples/README.md`](https://github.com/guizaols/insika/tree/main/examples/README.md)
20
+ (`examples/README.md` when the repo is checked out). Read it first.
21
+
22
+ ## Step 0 — Gather context (do this first, silently)
23
+
24
+ RULES — verify, do not assume:
25
+
26
+ - **Ruby ≥ 3.3.** Run `ruby -v`. If lower, stop and tell the developer; do not try to
27
+ upgrade Ruby for them.
28
+ - **Insika must be loadable** — `require "insika"` (installed gem) or the checked-out
29
+ repo's bundle. Do not copy source files around to "fix" a missing install.
30
+ - **A provider key comes from the environment** (`DEEPSEEK_API_KEY` for the demo).
31
+ None is set → **ask the developer**; never invent or hard-code one.
32
+ - **Read each example's own `README.md` before running it.** Some need more than one
33
+ terminal or extra env vars; the README is the contract.
34
+
35
+ ## Step 1 — Run in this order, ONE at a time
36
+
37
+ | # | Example | Command | Note |
38
+ |---|---------|---------|------|
39
+ | 1 | hello-agent | `ruby examples/hello-agent/hello.rb` | smallest agent; one turn |
40
+ | 2 | data-tool | `ruby examples/data-tool/currency_agent.rb` | declarative HTTP tool + the egress guard |
41
+ | 3 | skills | `ruby examples/skills/skill_agent.rb` | progressive skill loading |
42
+ | 4 | memory | `ruby examples/memory/memory_agent.rb` | cross-session `remember` |
43
+ | 5 | guardrails | `ruby examples/guardrails/guarded_agent.rb` | content-safety guardrails |
44
+ | 6 | agentic-workflows | `ruby examples/agentic-workflows/sequential.rb` | then routing/parallel/delegation/evaluator |
45
+ | 7 | scheduled-report | `ruby examples/scheduled-report/report_agent.rb` | runs one report turn inline; add `--serve` only if asked |
46
+ | 8 | relay-channel | see its README | TWO processes + env vars; skip unless asked |
47
+
48
+ For each one: read its README → run → quote what it printed → explain in ≤ 3 lines
49
+ what capability it demonstrated.
50
+
51
+ Skip unless the developer asks: `insika-code/` (a full deployment, not a one-file
52
+ script), `quickstart.rb` (hello-agent already covers it), and anything in `examples/`
53
+ the table above does not list.
54
+
55
+ ## Step 2 — When one fails
56
+
57
+ - **Auth or model error** → stop that example, report the exact error, ask for a valid
58
+ key/model id. Never retry with a guessed id.
59
+ - **A cause you can read from the output** (missing env var, port already bound…) →
60
+ say so and fix only with the developer's OK.
61
+ - **Never edit an example to make it pass silently.** An example that needed a change
62
+ to run is a finding, not noise.
63
+
64
+ ## Step 3 — Self-check before you report done
65
+
66
+ - [ ] Every example above either printed real model output or was reported blocked,
67
+ with the exact blocker.
68
+ - [ ] No provider key written into any file; no invented model ids.
69
+ - [ ] Each example got its ≤ 3-line "what this demonstrates".
70
+ - [ ] Nothing was edited to make a failure disappear.
data/docs/reference.md ADDED
@@ -0,0 +1,19 @@
1
+ ---
2
+ title: Reference
3
+ nav_order: 8
4
+ has_children: true
5
+ permalink: /reference/
6
+ ---
7
+
8
+ # Reference
9
+
10
+ The removability map, plus the paste-prompts that hand a journey to a coding
11
+ agent. A running instance serves each prompt at `GET /docs/<name>.md`, so you can
12
+ point Claude Code, Codex or Cursor at the URL instead of pasting the text.
13
+
14
+ - **[The domain-free core](domain.md)** — what ships in the gem, what a deployment declares, and how to clear it.
15
+ - **[Prompt — run every example](prompts/RUN-EXAMPLES.md)** — run `examples/` one at a time and explain what each proves.
16
+ - **[Prompt — add a tool or skill](prompts/ADD-TOOL.md)** — pick the right kind, wire the allowlist, prove it with one turn.
17
+ - **[Prompt — diagnose a failed turn](prompts/DIAGNOSE-TURN.md)** — symptom to mechanism, then fix one thing.
18
+ - **[Prompt — go live](prompts/GO-LIVE.md)** — tokens, volume, deploy, one authenticated turn, and the backup hole.
19
+ {: .card-grid }
data/docs/ship.md CHANGED
@@ -1,10 +1,18 @@
1
1
  ---
2
2
  title: Ship it
3
- nav_order: 4
3
+ nav_order: 5
4
4
  has_children: true
5
5
  permalink: /ship/
6
6
  ---
7
7
 
8
8
  # Ship it
9
9
 
10
- What stands between your agent and the open internet, and how to put it on a server.
10
+ What stands between your agent and the open internet, and how to put it on a
11
+ server without losing a turn to a restart.
12
+
13
+ - **[Security](SECURITY.md)** — guardrails, egress, approvals, secrets, and the privacy obligations that come with memory.
14
+ - **[Sandbox](SANDBOX.md)** — confined execution for tool code you did not write.
15
+ - **[Deploy](DEPLOY.md)** — the container, the durable volume, the process model, and the full environment table.
16
+ - **[Router](ROUTER.md)** — the session-sticky proxy that lets you run more than one worker.
17
+ - **[Releasing](RELEASING.md)** — how the gem is cut, and the install proof that runs before it is published.
18
+ {: .card-grid }
@@ -0,0 +1,18 @@
1
+ ---
2
+ title: Start here
3
+ nav_order: 2
4
+ has_children: true
5
+ permalink: /start-here/
6
+ ---
7
+
8
+ # Start here
9
+
10
+ Four pages, in order: what problem the runtime solves, how to get one running on
11
+ your machine, what actually happens inside a turn, and how to fill an empty
12
+ install with enough data to see every loop working.
13
+
14
+ - **[Why Insika](WHY.md)** — a runtime instead of a hand-rolled loop, an assembled framework, or a hosted gateway.
15
+ - **[Running locally](RUNNING-LOCAL.md)** — boot the engine, open the control UI, point a Responses client at it.
16
+ - **[Architecture](ARCHITECTURE.md)** — the turn pipeline, the tool-loop, checkpoint recovery, the concurrency model.
17
+ - **[Demo data](DEMO.md)** — seed a deployment so funnels, refinement and approvals have something to show.
18
+ {: .card-grid }