create-loopengine 0.1.7 → 0.1.9

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-loopengine",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Scaffold a new loopengine agent project — a runnable HTTP server with one example agent, in your own repo.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -33,24 +33,31 @@ npm run cli -- --agent example-agent "what is the weather in Boston?"
33
33
 
34
34
  ## Add another agent
35
35
 
36
- 1. Copy `agents/example-agent.ts` to `agents/your-agent.ts` and edit its
37
- `name`, `systemPrompt`, `tools`, and `rules`.
38
- 2. That's it — `agent-registry.ts` discovers it automatically by
36
+ 1. Copy `agents/example-agent/` to `agents/your-agent/` — `index.ts`
37
+ (persona + which tools), `tools/` (one file per tool), `actauth.yml`
38
+ (the permission story), and `skills/` if it needs any.
39
+ 2. Edit `index.ts`'s `name` and `systemPrompt`, and `tools/index.ts`'s
40
+ tool list. `rules`/`skillsDirs` don't need touching — they're left
41
+ unset in `index.ts` on purpose, so they keep defaulting to
42
+ `actauth.yml`/`skills/` next to it.
43
+ 3. That's it — `agent-registry.ts` discovers it automatically by
39
44
  `AgentConfig.name`, no registration step. Nothing to edit, no import to
40
45
  add, no adapter change.
41
- 3. Call it at `/agents/your-agent/messages`.
46
+ 4. Call it at `/agents/your-agent/messages`.
42
47
 
43
- A flat file like this is enough for most agents. An agent can also be a
44
- *folder* — `agents/your-agent/index.ts` instead of `agents/your-agent.ts`
45
- — which unlocks per-agent `tools/`, `skills/`, and `actauth.yml` defaults,
46
- and lets it have its own subagents (see below). `loopengine`'s own CLI
47
- scaffolds that folder form for you:
48
+ `loopengine`'s own CLI scaffolds this same folder shape for you, if you'd
49
+ rather start empty than copy `example-agent/`:
48
50
 
49
51
  ```bash
50
52
  npx loopengine add-agent your-agent
51
53
  # -> Created agents/your-agent/index.ts
52
54
  ```
53
55
 
56
+ An agent can also be a single flat file — `agents/your-agent.ts` instead
57
+ of a folder — if it's simple enough not to need its own `tools/`,
58
+ `skills/`, or `actauth.yml`. It just can't have subagents (see below),
59
+ since there's no folder for `subagents/` to live under.
60
+
54
61
  ## Composing agents (subagents)
55
62
 
56
63
  An agent's tools can be other agents. Drop a folder under
@@ -77,10 +84,13 @@ reaching for this.
77
84
  ## Project layout
78
85
 
79
86
  ```
80
- agent-registry.ts Auto-discovers agents/*.ts by AgentConfig.name — nothing to edit here
81
- agents/example-agent.ts Starter agent: persona, one tool, one permission rule
82
- adapters/http.ts HTTP API (streaming + non-streaming)
83
- adapters/cli.ts Command-line adapter
87
+ agent-registry.ts Auto-discovers agents/* by AgentConfig.name — nothing to edit here
88
+ agents/example-agent/index.ts Starter agent: persona, one tool
89
+ agents/example-agent/tools/ One tool (get_weather), aggregated in tools/index.ts
90
+ agents/example-agent/actauth.yml One permission rule (allow get_weather), default_decision: ask
91
+ agents/example-agent/skills/ One skill (convert-temperature) — instructions, not a tool call
92
+ adapters/http.ts HTTP API (streaming + non-streaming)
93
+ adapters/cli.ts Command-line adapter
84
94
  ```
85
95
 
86
96
  ## Adding external tools via Composio
@@ -0,0 +1,12 @@
1
+ # The permission story for this agent: which tool, which rule, allow or
2
+ # ask. Loaded automatically because index.ts doesn't set `rules` itself —
3
+ # omitting it defaults to this file, agents/<name>/actauth.yml, resolved
4
+ # from wherever you run the process (see AgentConfig.rules's own doc
5
+ # comment in loopengine for the full resolution rules).
6
+ default_decision: ask
7
+
8
+ rules:
9
+ - name: get-weather-always-allowed
10
+ scope: "*/*"
11
+ tool: get_weather
12
+ decision: allow
@@ -0,0 +1,29 @@
1
+ // A starting point, not a template to copy verbatim: real persona, real
2
+ // tool, real permission rule — one folder per agent, the same convention
3
+ // agents/customer-service/ uses in loopengine's own repo. Add more agents
4
+ // by copying this whole folder under a new name and a new AgentConfig.name
5
+ // — agent-registry.ts discovers it automatically, nothing to register by
6
+ // hand.
7
+ //
8
+ // `rules` and `skillsDirs` are both left unset here on purpose — omitting
9
+ // them defaults to actauth.yml and skills/ alongside this file (loopengine
10
+ // resolves both relative to wherever you run the process). `tools` is set
11
+ // explicitly instead of relying on the equivalent tools/ default: that one
12
+ // resolves relative to loopengine's own installed location, not your
13
+ // project, so it only works inside loopengine's own repo — see
14
+ // tools/index.ts's own comment.
15
+ import { createAnthropicModelCall, type AgentConfig, type ModelCall } from 'loopengine'
16
+ import { tools } from './tools/index.js'
17
+
18
+ export const config: AgentConfig = {
19
+ name: 'example-agent',
20
+ systemPrompt: 'You are a helpful assistant.',
21
+ tools,
22
+ }
23
+
24
+ // Reads ANTHROPIC_API_KEY from the env. Swap for
25
+ // createOpenAIModelCall({ model: '...' }) to use OpenAI instead — see
26
+ // node_modules/loopengine/README.md's "Wiring a real model" section.
27
+ export function createModelCall(): ModelCall {
28
+ return createAnthropicModelCall({ model: 'claude-sonnet-5' })
29
+ }
@@ -0,0 +1,11 @@
1
+ ---
2
+ name: convert-temperature
3
+ description: Convert a temperature between Celsius and Fahrenheit without a tool call.
4
+ ---
5
+
6
+ # Convert temperature
7
+
8
+ To convert Celsius to Fahrenheit: multiply by 9/5, then add 32.
9
+ To convert Fahrenheit to Celsius: subtract 32, then multiply by 5/9.
10
+
11
+ Do the arithmetic yourself and show the result — no tool needed for this.
@@ -0,0 +1,8 @@
1
+ import type { ToolDefinition } from 'loopengine'
2
+
3
+ export const getWeather: ToolDefinition = {
4
+ name: 'get_weather',
5
+ description: 'Look up the weather for a city',
6
+ input_schema: { type: 'object', properties: { city: { type: 'string' } }, required: ['city'] },
7
+ execute: async (input) => `Sunny in ${input.city}`,
8
+ }
@@ -0,0 +1,12 @@
1
+ // Aggregates this agent's tools — one file per tool, so adding another
2
+ // tool later means adding a file here and one line below, not touching
3
+ // index.ts. Mirrors loopengine's own agents/customer-service/tools/index.ts,
4
+ // except index.ts here imports this file explicitly (`tools,` in its
5
+ // AgentConfig) rather than omitting `tools` and relying on loopengine's
6
+ // own auto-import of this exact path: that default is resolved relative
7
+ // to loopengine's own installed location, so it only finds a tools/
8
+ // folder that lives inside loopengine's own repo, not your project's.
9
+ import type { ToolDefinition } from 'loopengine'
10
+ import { getWeather } from './get_weather.js'
11
+
12
+ export const tools: ToolDefinition[] = [getWeather]
@@ -9,7 +9,7 @@
9
9
  "cli": "tsx adapters/cli.ts"
10
10
  },
11
11
  "dependencies": {
12
- "loopengine": "^0.0.17"
12
+ "loopengine": "^0.1.3"
13
13
  },
14
14
  "devDependencies": {
15
15
  "@types/node": "^22.10.0",
@@ -1,27 +0,0 @@
1
- // A starting point, not a template to copy verbatim: real persona, real
2
- // tool, real permission rule. Add more agents by copying this file into
3
- // agents/ under a new filename and a new AgentConfig.name — agent-registry.ts
4
- // discovers it automatically, nothing to register by hand.
5
- import { createAnthropicModelCall, type AgentConfig, type ModelCall } from 'loopengine'
6
-
7
- export const config: AgentConfig = {
8
- name: 'example-agent',
9
- systemPrompt: 'You are a helpful assistant.',
10
- tools: [
11
- {
12
- name: 'get_weather',
13
- description: 'Look up the weather for a city',
14
- input_schema: { type: 'object', properties: { city: { type: 'string' } }, required: ['city'] },
15
- execute: async (input) => `Sunny in ${input.city}`,
16
- },
17
- ],
18
- rules: [{ scopePattern: 'default/production/example-agent', tool: 'get_weather', decision: 'allow' }],
19
- defaultDecision: 'ask',
20
- }
21
-
22
- // Reads ANTHROPIC_API_KEY from the env. Swap for
23
- // createOpenAIModelCall({ model: '...' }) to use OpenAI instead — see
24
- // node_modules/loopengine/README.md's "Wiring a real model" section.
25
- export function createModelCall(): ModelCall {
26
- return createAnthropicModelCall({ model: 'claude-sonnet-5' })
27
- }