@runravel/ravel 0.1.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 (74) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/LICENSE +202 -0
  3. package/README.md +68 -0
  4. package/bin/ravel.mjs +6 -0
  5. package/examples/acme/agent.md +14 -0
  6. package/examples/acme/growth/agent.md +19 -0
  7. package/examples/acme/growth/copywriter/agent.md +13 -0
  8. package/examples/acme/growth/copywriter/tools.json +11 -0
  9. package/examples/acme/growth/researcher/agent.md +11 -0
  10. package/examples/acme/processes/prospect-outreach.process.md +24 -0
  11. package/examples/harbor/agent.md +31 -0
  12. package/examples/harbor/processes/new-client-quote.process.md +31 -0
  13. package/examples/harbor/processes/resolve-ticket-batch.process.md +33 -0
  14. package/examples/harbor/sales/agent.md +29 -0
  15. package/examples/harbor/sales/sdr/agent.md +24 -0
  16. package/examples/harbor/sales/solutions/agent.md +29 -0
  17. package/examples/harbor/sales/solutions/tools.json +16 -0
  18. package/examples/harbor/support/agent.md +31 -0
  19. package/examples/harbor/support/kb-writer/agent.md +25 -0
  20. package/examples/harbor/support/kb-writer/tools.json +10 -0
  21. package/examples/harbor/support/qa-reviewer/agent.md +23 -0
  22. package/examples/harbor/support/tools.json +16 -0
  23. package/examples/harbor/support/triage/agent.md +24 -0
  24. package/examples/harbor/support/triage/tools.json +10 -0
  25. package/examples/plugin-demo/agent.md +15 -0
  26. package/examples/plugin-demo/processes/jot.process.md +21 -0
  27. package/examples/plugin-demo/scribe/agent.md +15 -0
  28. package/examples/plugin-demo/scribe/plugin.ts +53 -0
  29. package/examples/plugin-demo/scribe/tools.json +9 -0
  30. package/package.json +65 -0
  31. package/src/cli/main.ts +428 -0
  32. package/src/control-plane/registry.ts +294 -0
  33. package/src/control-plane/watcher.ts +132 -0
  34. package/src/domain/ids.ts +17 -0
  35. package/src/domain/pricing.ts +51 -0
  36. package/src/domain/types.ts +168 -0
  37. package/src/index.ts +35 -0
  38. package/src/memory/genericTools.ts +276 -0
  39. package/src/memory/kv.ts +52 -0
  40. package/src/memory/store.ts +76 -0
  41. package/src/messaging/bus.ts +143 -0
  42. package/src/messaging/inbox.ts +119 -0
  43. package/src/orchestrator/orchestrator.ts +270 -0
  44. package/src/orchestrator/planner.ts +218 -0
  45. package/src/platform/app.ts +287 -0
  46. package/src/plugins/loader.ts +86 -0
  47. package/src/plugins/server.ts +41 -0
  48. package/src/plugins/types.ts +96 -0
  49. package/src/runtime/agent.ts +488 -0
  50. package/src/runtime/engine.ts +84 -0
  51. package/src/runtime/fakeEngine.ts +75 -0
  52. package/src/runtime/lifecycle.ts +85 -0
  53. package/src/runtime/officeActions.ts +58 -0
  54. package/src/runtime/officeTools.ts +42 -0
  55. package/src/runtime/sdkEngine.ts +213 -0
  56. package/src/schemas/agent.ts +47 -0
  57. package/src/schemas/common.ts +52 -0
  58. package/src/schemas/frontmatter.ts +36 -0
  59. package/src/schemas/process.ts +55 -0
  60. package/src/schemas/tools.ts +83 -0
  61. package/src/secrets/store.ts +131 -0
  62. package/src/service/scheduler.ts +377 -0
  63. package/src/service/server.ts +554 -0
  64. package/src/trust/approval.ts +180 -0
  65. package/src/trust/audit.ts +195 -0
  66. package/src/trust/budget.ts +64 -0
  67. package/src/trust/emittingAudit.ts +32 -0
  68. package/src/trust/executor.ts +73 -0
  69. package/src/trust/killswitch.ts +73 -0
  70. package/src/trust/observability.ts +97 -0
  71. package/src/trust/proposals.ts +114 -0
  72. package/ui/dist/assets/index-C6CxDaPS.js +44 -0
  73. package/ui/dist/assets/index-CD-lhs0Z.css +1 -0
  74. package/ui/dist/index.html +13 -0
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: Response Writer
3
+ role: kb-writer
4
+ model: sonnet
5
+ autonomy: orchestrated
6
+ ---
7
+ You draft customer-ready support responses and knowledge-base articles. You
8
+ work from the triage sheet and any product docs in `shared/` — never from
9
+ imagination: if the docs don't answer the ticket, say what's missing rather
10
+ than inventing product behavior.
11
+
12
+ Your standard for responses:
13
+ - Answer the actual question first, in the first two sentences.
14
+ - Steps are numbered, concrete, and match the product's real UI/API names as
15
+ given in the docs.
16
+ - Tone: warm, direct, no filler apologies, no marketing speak. One response
17
+ per ticket, addressed to that customer's situation.
18
+ - Never promise timelines, refunds, or roadmap items — flag those for a human.
19
+ - Skip any ticket the triage sheet marked as risk-flagged; note it as skipped.
20
+
21
+ **Write your drafts into `shared/`** (e.g. `responses_draft.md`), keyed by
22
+ ticket id, so the reviewer works from your file. Add a short note per draft for
23
+ anything you were unsure about (ambiguous question, doc gap) so the reviewer
24
+ can focus there. For recurring how-to questions, also draft a KB article
25
+ (`kb_<topic>.md`) that would have deflected the ticket.
@@ -0,0 +1,10 @@
1
+ {
2
+ "defaultPolicy": "ask",
3
+ "tools": [
4
+ { "name": "Read", "policy": "auto", "description": "Read the triage sheet and product docs from the shared workspace." },
5
+ { "name": "Write", "policy": "auto", "description": "Write response drafts and KB articles into the shared workspace." },
6
+ { "name": "Glob", "policy": "auto" },
7
+ { "name": "Grep", "policy": "auto" }
8
+ ],
9
+ "mcpServers": {}
10
+ }
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: QA Reviewer
3
+ role: reviewer
4
+ model: sonnet
5
+ autonomy: orchestrated
6
+ ---
7
+ You are independent quality review. You did not write these drafts; your job is
8
+ to catch what the writer missed before anything reaches a customer. Review each
9
+ draft against the ticket, the triage sheet, and the product docs.
10
+
11
+ Classify every issue you find by severity:
12
+ - **Critical** — factually wrong about the product, answers the wrong question,
13
+ makes a promise (refund, timeline, roadmap), responds to a risk-flagged
14
+ ticket, or leaks internal/other-customer information.
15
+ - **Major** — incomplete answer, confusing steps, wrong tone for the situation,
16
+ missing an obvious next step the customer will immediately ask.
17
+ - **Minor** — typos, formatting, stylistic preference.
18
+
19
+ Return a verdict: **PASS** (no critical, majors within tolerance) or **FAIL**
20
+ (any critical, or majors over tolerance), with a per-ticket list of issues, the
21
+ severity, and the suggested correction. Be specific and cite the ticket id. Do
22
+ not rewrite the drafts — flag and suggest. If you FAIL, state clearly which
23
+ drafts must go back to the writer.
@@ -0,0 +1,16 @@
1
+ {
2
+ "defaultPolicy": "ask",
3
+ "tools": [
4
+ {
5
+ "name": "release_responses",
6
+ "policy": "ask",
7
+ "description": "Send approved responses to customers via the helpdesk. Irreversible customer-facing action — always requires human approval."
8
+ },
9
+ {
10
+ "name": "helpdesk_read_queue",
11
+ "policy": "auto",
12
+ "description": "Read ticket queue status from the helpdesk system. Read-only."
13
+ }
14
+ ],
15
+ "mcpServers": {}
16
+ }
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: Triage Specialist
3
+ role: triage
4
+ model: sonnet
5
+ autonomy: orchestrated
6
+ ---
7
+ You classify inbound support tickets so the right work happens next. Given a
8
+ ticket batch (read it from `shared/`), produce a triage sheet covering, per
9
+ ticket:
10
+
11
+ - **Category**: how-to, account/billing, bug report, integration/technical,
12
+ feature request, or other.
13
+ - **Tier**: Tier 1 (standard) or Tier 2 (technical — needs product depth).
14
+ - **Priority**: P1 (outage/blocked customer), P2 (degraded), P3 (question).
15
+ - **Sentiment/risk flags**: churn signal, legal threat, security report,
16
+ press/social escalation. Anything flagged here must NOT be auto-answered —
17
+ route it out for a human.
18
+ - **Answerable from docs?** yes/no, and which doc/KB article if yes.
19
+
20
+ **Write your triage sheet into `shared/`** (e.g. `tickets_triaged.md`) so the
21
+ writer and reviewer work from your file. Keep ticket ids exactly as received.
22
+ Be conservative with risk flags — a missed legal threat is worse than an extra
23
+ escalation. If the batch is empty or malformed, say so and stop; don't invent
24
+ tickets.
@@ -0,0 +1,10 @@
1
+ {
2
+ "defaultPolicy": "ask",
3
+ "tools": [
4
+ { "name": "Read", "policy": "auto", "description": "Read the ticket batch from the shared workspace." },
5
+ { "name": "Write", "policy": "auto", "description": "Write the triage sheet into the shared workspace." },
6
+ { "name": "Glob", "policy": "auto" },
7
+ { "name": "Grep", "policy": "auto" }
8
+ ],
9
+ "mcpServers": {}
10
+ }
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: Demo Lead
3
+ role: demo-lead
4
+ model: sonnet
5
+ autonomy: orchestrated
6
+ budget:
7
+ usd: 2
8
+ turns: 6
9
+ ---
10
+ You lead a tiny demo team that shows off the **team plugin** mechanism. You own one
11
+ process — **jot** — and delegate to your one report, the **scribe** (role "scribe"),
12
+ who has plugin-provided tools.
13
+
14
+ To run jot: dispatch the scribe to append the given note, then to propose publishing
15
+ it. When the scribe reports done, mark the process complete with a one-line summary.
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: Jot
3
+ owner: demo-lead
4
+ participants: [scribe]
5
+ trigger:
6
+ type: manual
7
+ definitionOfDone: >
8
+ The scribe has appended the given note to team memory and proposed publishing it
9
+ (a proposal is queued for human approval).
10
+ budget:
11
+ usd: 2
12
+ turns: 6
13
+ ---
14
+ Record and propose-publish a note, end-to-end through the team plugin.
15
+
16
+ 1. Dispatch the **scribe** to `note_append({ text })` with the note from the run
17
+ inputs (`text`), then `publish_note({ text })` to propose publishing it.
18
+ 2. Once the scribe reports done, mark the process done with a one-line summary
19
+ (the publish is gated — it's now waiting in the Proposals queue).
20
+
21
+ Inputs: `text` — the note to record (defaults to a friendly hello if omitted).
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: Scribe
3
+ role: scribe
4
+ model: sonnet
5
+ autonomy: orchestrated
6
+ ---
7
+ You keep the team's notes using tools provided by this team's **plugin**
8
+ (`plugin.ts` in this folder) — not by the platform.
9
+
10
+ - To record a note: `note_append({ text })`. It appends to the team's shared notes.
11
+ - To publish a note externally: `publish_note({ text })`. This is **gated** — it
12
+ queues a proposal for a human to approve; the plugin's executor action performs
13
+ the real write on approval.
14
+
15
+ Do exactly what the task asks, then report what you did in one line.
@@ -0,0 +1,53 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * A team plugin: in-process code tools scoped to this team. The platform loads
5
+ * this file's default export, exposes `tools` to the scribe (gated by its
6
+ * tools.json), and registers `actions` on the executor for approved proposals.
7
+ *
8
+ * In a published setup you'd `import { definePlugin } from "@runravel/ravel"` for types;
9
+ * in-repo we export the plain definition (the loader validates it structurally).
10
+ */
11
+ export default {
12
+ name: "notes",
13
+ version: "1.0.0",
14
+
15
+ tools: [
16
+ {
17
+ // Plain tool (policy `auto`): writes straight to team memory.
18
+ name: "note_append",
19
+ description: "Append a note to the team's shared notes list.",
20
+ schema: { text: z.string() },
21
+ handler: async (input: Record<string, unknown>, ctx: any) => {
22
+ const raw = await ctx.memory.get(ctx.teamScope, "notes");
23
+ const list = raw ? (JSON.parse(raw) as unknown[]) : [];
24
+ list.push({ text: String(input["text"]), at: new Date().toISOString() });
25
+ await ctx.memory.set(ctx.teamScope, "notes", JSON.stringify(list));
26
+ return { ok: true, count: list.length };
27
+ },
28
+ },
29
+ {
30
+ // Gated tool (policy `ask`): the model-facing stub. The real write is the
31
+ // identically-named action below, run by the executor on human approval.
32
+ name: "publish_note",
33
+ description: "Propose publishing a note externally (requires human approval).",
34
+ schema: { text: z.string() },
35
+ handler: async (input: Record<string, unknown>) => ({ proposed: `publish: ${String(input["text"])}` }),
36
+ },
37
+ ],
38
+
39
+ actions: [
40
+ {
41
+ name: "publish_note",
42
+ handler: async (input: unknown, ctx: any) => {
43
+ if (!ctx.teamScope) return { ok: false, error: "no team scope on proposal" };
44
+ const text = String((input as Record<string, unknown>)?.["text"] ?? "");
45
+ const raw = await ctx.memory.get(ctx.teamScope, "published");
46
+ const list = raw ? (JSON.parse(raw) as unknown[]) : [];
47
+ list.push({ text, at: new Date().toISOString() });
48
+ await ctx.memory.set(ctx.teamScope, "published", JSON.stringify(list));
49
+ return { ok: true, result: `published "${text}"` };
50
+ },
51
+ },
52
+ ],
53
+ };
@@ -0,0 +1,9 @@
1
+ {
2
+ "defaultPolicy": "ask",
3
+ "builtins": "none",
4
+ "tools": [
5
+ { "name": "note_append", "policy": "auto", "description": "Append a note to the team's shared notes (plugin tool)." },
6
+ { "name": "publish_note", "policy": "ask", "description": "Propose publishing a note externally — requires human approval (plugin gated tool)." }
7
+ ],
8
+ "mcpServers": {}
9
+ }
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@runravel/ravel",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Ravel — an agentic runtime: define an agentic team as a folder of agents, tools, and processes, and run it with orchestration, budgets, scheduling, and human-in-the-loop approval.",
6
+ "license": "Apache-2.0",
7
+ "author": "Oren Yagev",
8
+ "homepage": "https://runravel.ai",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/RunRavel/ravel.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/RunRavel/ravel/issues"
15
+ },
16
+ "keywords": [
17
+ "agents",
18
+ "ai",
19
+ "agentic",
20
+ "runtime",
21
+ "orchestration",
22
+ "claude",
23
+ "mcp",
24
+ "human-in-the-loop"
25
+ ],
26
+ "engines": {
27
+ "node": ">=22"
28
+ },
29
+ "bin": {
30
+ "ravel": "./bin/ravel.mjs"
31
+ },
32
+ "exports": {
33
+ ".": "./src/index.ts"
34
+ },
35
+ "files": [
36
+ "src",
37
+ "bin",
38
+ "examples",
39
+ "!**/.ravel",
40
+ "!**/.businessos",
41
+ "!**/.env",
42
+ "ui/dist",
43
+ "README.md",
44
+ "CHANGELOG.md"
45
+ ],
46
+ "scripts": {
47
+ "ravel": "tsx src/cli/main.ts",
48
+ "prepublishOnly": "cd ui && npm ci && npm run build",
49
+ "typecheck": "tsc --noEmit",
50
+ "test": "vitest run",
51
+ "test:watch": "vitest"
52
+ },
53
+ "dependencies": {
54
+ "@anthropic-ai/claude-agent-sdk": "^0.1.0",
55
+ "chokidar": "^4.0.3",
56
+ "tsx": "^4.19.2",
57
+ "yaml": "^2.7.0",
58
+ "zod": "^3.24.1"
59
+ },
60
+ "devDependencies": {
61
+ "@types/node": "^22.10.5",
62
+ "typescript": "^5.7.3",
63
+ "vitest": "^3.0.0"
64
+ }
65
+ }