create-loopengine 0.1.8 → 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 +1 -1
- package/template/README.md +23 -13
- package/template/agents/example-agent/actauth.yml +12 -0
- package/template/agents/example-agent/index.ts +29 -0
- package/template/agents/example-agent/skills/convert-temperature/SKILL.md +11 -0
- package/template/agents/example-agent/tools/get_weather.ts +8 -0
- package/template/agents/example-agent/tools/index.ts +12 -0
- package/template/package.json +1 -1
- package/template/agents/example-agent.ts +0 -27
package/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -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
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
46
|
+
4. Call it at `/agents/your-agent/messages`.
|
|
42
47
|
|
|
43
|
-
|
|
44
|
-
|
|
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
|
|
81
|
-
agents/example-agent.ts
|
|
82
|
-
|
|
83
|
-
|
|
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]
|
package/template/package.json
CHANGED
|
@@ -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
|
-
}
|