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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +296 -0
- data/README.md +48 -12
- data/bin/insika +725 -0
- data/bin/insika-router +87 -0
- data/docs/AGENTS.md +116 -406
- data/docs/API.md +5 -5
- data/docs/ARCHITECTURE.md +3 -2
- data/docs/ARTIFACTS.md +137 -0
- data/docs/BENCHMARK.md +2 -2
- data/docs/CHANNELS.md +14 -14
- data/docs/CONTEXT.md +63 -19
- data/docs/DEMO.md +80 -0
- data/docs/DEPLOY.md +87 -10
- data/docs/EMBEDDING.md +1 -1
- data/docs/EVALS.md +128 -3
- data/docs/FACTS.md +3 -3
- data/docs/HARVEST.md +5 -6
- data/docs/KNOWLEDGE.md +290 -0
- data/docs/LOADTEST.md +17 -29
- data/docs/MEDIA.md +128 -0
- data/docs/OBSERVABILITY.md +46 -12
- data/docs/OUTCOMES.md +137 -0
- data/docs/PLUGINS.md +51 -6
- data/docs/POLICY.md +222 -0
- data/docs/REFINEMENT.md +14 -9
- data/docs/RELEASING.md +4 -4
- data/docs/ROUTER.md +213 -0
- data/docs/RUNNING-LOCAL.md +5 -5
- data/docs/SCHEDULING.md +121 -0
- data/docs/SECURITY.md +23 -7
- data/docs/SKILLS.md +11 -2
- data/docs/SOAK.md +3 -3
- data/docs/TEMPLATES.md +134 -0
- data/docs/TOOLS.md +176 -27
- data/docs/WHY.md +1 -1
- data/docs/WORKFLOWS.md +2 -2
- data/docs/_includes/head_custom.html +5 -0
- data/docs/_includes/title.html +13 -0
- data/docs/_sass/color_schemes/insika.scss +32 -0
- data/docs/_sass/custom/custom.scss +199 -0
- data/docs/_sass/custom/setup.scss +26 -0
- data/docs/assets/img/favicon.svg +7 -0
- data/docs/assets/img/insika-mark.svg +7 -0
- data/docs/core-concepts.md +21 -0
- data/docs/domain.md +4 -4
- data/docs/improve.md +20 -0
- data/docs/index.md +8 -5
- data/docs/integrate.md +20 -0
- data/docs/operate.md +13 -6
- data/docs/prompts/ADD-TOOL.md +118 -0
- data/docs/prompts/DIAGNOSE-TURN.md +65 -0
- data/docs/prompts/GO-LIVE.md +138 -0
- data/docs/prompts/RUN-EXAMPLES.md +70 -0
- data/docs/reference.md +19 -0
- data/docs/ship.md +10 -2
- data/docs/start-here.md +18 -0
- data/lib/insika/agent_profile.rb +99 -17
- data/lib/insika/artifact_signing.rb +82 -0
- data/lib/insika/artifact_store.rb +160 -0
- data/lib/insika/channel_delivery.rb +1 -1
- data/lib/insika/chat_builder.rb +50 -19
- data/lib/insika/commands/agent_payload.rb +2 -2
- data/lib/insika/commands/backfill_knowledge.rb +145 -0
- data/lib/insika/commands/delete_artifact.rb +35 -0
- data/lib/insika/commands/delete_concept.rb +34 -0
- data/lib/insika/commands/delete_mcp.rb +6 -2
- data/lib/insika/commands/delete_tenant_data.rb +15 -3
- data/lib/insika/commands/gate_refinement.rb +1 -1
- data/lib/insika/commands/refresh_mcp_tools.rb +47 -0
- data/lib/insika/commands/restore_concept.rb +34 -0
- data/lib/insika/commands/seed_demo_data.rb +31 -0
- data/lib/insika/commands/upsert_mcp.rb +6 -3
- data/lib/insika/commands/write_concept.rb +57 -0
- data/lib/insika/compaction.rb +196 -0
- data/lib/insika/context/builder.rb +6 -2
- data/lib/insika/context/fragment.rb +4 -1
- data/lib/insika/context/priority.rb +8 -0
- data/lib/insika/context/providers/briefing.rb +53 -24
- data/lib/insika/context/providers/knowledge.rb +108 -0
- data/lib/insika/context/providers/prompt.rb +30 -24
- data/lib/insika/context/providers/session.rb +46 -10
- data/lib/insika/context_trace_store.rb +11 -1
- data/lib/insika/cron.rb +189 -0
- data/lib/insika/demo/agent_attrs.rb +43 -0
- data/lib/insika/demo/golden_cases.rb +81 -0
- data/lib/insika/demo/seeder.rb +336 -0
- data/lib/insika/doctor.rb +280 -17
- data/lib/insika/dsl/definition.rb +3 -2
- data/lib/insika/dsl/runtime.rb +64 -79
- data/lib/insika/dsl/server_boot.rb +23 -1
- data/lib/insika/dsl/system.rb +10 -2
- data/lib/insika/dsl.rb +103 -2
- data/lib/insika/env_schema.rb +21 -7
- data/lib/insika/evals/golden.rb +41 -4
- data/lib/insika/evals/judge.rb +47 -2
- data/lib/insika/evals/pairwise.rb +11 -0
- data/lib/insika/evals/persona.rb +98 -0
- data/lib/insika/evals/runner.rb +9 -0
- data/lib/insika/evals/simulator.rb +225 -0
- data/lib/insika/evals/transport.rb +84 -2
- data/lib/insika/event_stream.rb +10 -0
- data/lib/insika/executor.rb +295 -55
- data/lib/insika/followup_policy.rb +2 -25
- data/lib/insika/golden_store.rb +16 -1
- data/lib/insika/grounding/matcher.rb +1 -1
- data/lib/insika/knowledge.rb +680 -0
- data/lib/insika/knowledge_store.rb +140 -0
- data/lib/insika/loop_detector.rb +5 -34
- data/lib/insika/mcp_client.rb +94 -0
- data/lib/insika/mcp_json.rb +74 -0
- data/lib/insika/mcp_live_tool.rb +43 -0
- data/lib/insika/mcp_store.rb +98 -26
- data/lib/insika/mcp_tool_ingestor.rb +30 -8
- data/lib/insika/mcp_tool_registry.rb +100 -0
- data/lib/insika/media.rb +115 -31
- data/lib/insika/message_origin.rb +1 -1
- data/lib/insika/middleware.rb +9 -0
- data/lib/insika/onboarding.rb +17 -1
- data/lib/insika/outcome_store.rb +1 -1
- data/lib/insika/overlay_tool_registry.rb +37 -17
- data/lib/insika/packaging.rb +2 -2
- data/lib/insika/profile_source.rb +15 -1
- data/lib/insika/prompt_catalog.rb +10 -0
- data/lib/insika/retention.rb +36 -1
- data/lib/insika/router/app.rb +157 -0
- data/lib/insika/router/backend_pool.rb +98 -0
- data/lib/insika/router/hash_ring.rb +55 -0
- data/lib/insika/router/proxy_body.rb +34 -0
- data/lib/insika/router/session_key.rb +54 -0
- data/lib/insika/router.rb +18 -0
- data/lib/insika/schedule.rb +177 -0
- data/lib/insika/schedule_engine.rb +314 -0
- data/lib/insika/schedule_store.rb +208 -0
- data/lib/insika/server/app.rb +105 -15
- data/lib/insika/server/rack_app.rb +5 -1
- data/lib/insika/server/responses.rb +5 -5
- data/lib/insika/session_store.rb +34 -4
- data/lib/insika/settings_store.rb +8 -1
- data/lib/insika/skill_catalog.rb +12 -0
- data/lib/insika/soak/runner.rb +4 -4
- data/lib/insika/steer_injector.rb +21 -10
- data/lib/insika/studio/app.rb +591 -47
- data/lib/insika/studio/assets/dist/application.css +1 -1
- data/lib/insika/studio/assets/dist/application.js +21 -21
- data/lib/insika/studio/forms.rb +57 -5
- data/lib/insika/studio/nav_icons.rb +14 -1
- data/lib/insika/studio/views/_agent_tab_cache.erb +25 -0
- data/lib/insika/studio/views/_agent_tab_config.erb +514 -0
- data/lib/insika/studio/views/_agent_tab_history.erb +24 -0
- data/lib/insika/studio/views/_agent_tab_loops.erb +54 -0
- data/lib/insika/studio/views/_agent_tab_memory.erb +51 -0
- data/lib/insika/studio/views/_agent_tab_outcomes.erb +31 -0
- data/lib/insika/studio/views/_agent_tab_prompts.erb +108 -0
- data/lib/insika/studio/views/_agent_tab_skills.erb +38 -0
- data/lib/insika/studio/views/_agents_master.erb +44 -0
- data/lib/insika/studio/views/_message.erb +49 -32
- data/lib/insika/studio/views/agent_detail.erb +61 -820
- data/lib/insika/studio/views/agents.erb +70 -57
- data/lib/insika/studio/views/artifact.erb +23 -0
- data/lib/insika/studio/views/artifacts.erb +59 -0
- data/lib/insika/studio/views/evals.erb +2 -2
- data/lib/insika/studio/views/facts.erb +1 -1
- data/lib/insika/studio/views/funnel.erb +1 -1
- data/lib/insika/studio/views/home.erb +106 -67
- data/lib/insika/studio/views/knowledge.erb +123 -0
- data/lib/insika/studio/views/layout.erb +14 -11
- data/lib/insika/studio/views/mcp.erb +174 -80
- data/lib/insika/studio/views/session.erb +231 -177
- data/lib/insika/studio/views/settings.erb +50 -1
- data/lib/insika/studio/views/skills.erb +1 -1
- data/lib/insika/studio/views/tools.erb +24 -9
- data/lib/insika/telemetry/recorder.rb +49 -1
- data/lib/insika/templates/browser-agent/README.md +36 -0
- data/lib/insika/templates/browser-agent/agent.rb +49 -0
- data/lib/insika/templates/daily-digest/README.md +47 -0
- data/lib/insika/templates/daily-digest/agent.rb +77 -0
- data/lib/insika/templates/repo-explorer/README.md +36 -0
- data/lib/insika/templates/repo-explorer/agent.rb +45 -0
- data/lib/insika/templates/research-analyst/README.md +26 -0
- data/lib/insika/templates/research-analyst/agent.rb +68 -0
- data/lib/insika/templates/review-panel/README.md +20 -0
- data/lib/insika/templates/review-panel/agent.rb +50 -0
- data/lib/insika/templates/travel-planner/README.md +35 -0
- data/lib/insika/templates/travel-planner/agent.rb +87 -0
- data/lib/insika/templates.rb +112 -0
- data/lib/insika/tick.rb +24 -12
- data/lib/insika/timezone.rb +45 -0
- data/lib/insika/tool_batch.rb +67 -0
- data/lib/insika/tool_usage_report.rb +162 -0
- data/lib/insika/tools/generate_image.rb +52 -7
- data/lib/insika/tools/load_knowledge.rb +74 -0
- data/lib/insika/tools/run_persona_eval.rb +328 -0
- data/lib/insika/tools/save_artifact.rb +95 -0
- data/lib/insika/turn_budget.rb +91 -0
- data/lib/insika/turn_output.rb +1 -1
- data/lib/insika/turn_state.rb +15 -4
- data/lib/insika/version.rb +1 -1
- data/lib/insika/wiring/graph.rb +184 -12
- data/lib/insika/wiring/graph_chat.rb +102 -0
- data/lib/insika.rb +64 -0
- metadata +109 -5
- data/docs/build.md +0 -14
- 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
|
-
{: .
|
|
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
|
-
- **[
|
|
64
|
-
- **[
|
|
65
|
-
- **[
|
|
66
|
-
- **[
|
|
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
|
|
3
|
-
nav_order:
|
|
2
|
+
title: Operate
|
|
3
|
+
nav_order: 6
|
|
4
4
|
has_children: true
|
|
5
5
|
permalink: /operate/
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Operate
|
|
8
|
+
# Operate
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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:
|
|
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
|
|
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 }
|
data/docs/start-here.md
ADDED
|
@@ -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 }
|