ernesto 0.0.2 → 0.0.3
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/README.md +193 -110
- package/REFERENCE.md +1399 -0
- package/dist/schema-formatter.cjs +10 -2
- package/dist/schema-formatter.cjs.map +1 -1
- package/dist/schema-formatter.js +10 -2
- package/dist/schema-formatter.js.map +1 -1
- package/dist/typesense/client.cjs +6 -20
- package/dist/typesense/client.cjs.map +1 -1
- package/dist/typesense/client.js +6 -20
- package/dist/typesense/client.js.map +1 -1
- package/package.json +1 -1
- package/src/schema-formatter.ts +10 -2
- package/src/typesense/client.ts +6 -22
package/README.md
CHANGED
|
@@ -1,164 +1,247 @@
|
|
|
1
|
-
# Ernesto
|
|
1
|
+
# Ernesto
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A context system that structures organizational knowledge and makes it accessible efficiently to AI agents.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## The Problem
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
Traditional approaches to AI agent tooling fail at scale:
|
|
8
10
|
|
|
9
|
-
**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
3. Route returns content + guidance: `["Check recent logs", "Analyze transaction patterns"]`
|
|
13
|
-
4. Agent follows guidance, gets deeper tools that weren't visible in initial search
|
|
11
|
+
- **Flat tool hierarchies** — Hundreds of tools at the same level, no structure. The agent must infer which tools relate to each other and in what order and how to use them. Often, the agent tends to use the most granular tool, which is also the harder to use.
|
|
12
|
+
- **No encoded workflows** — Raw API wrappers delegate business logic to the agent itself. It guesses at processes your organization has already figured out. Agent must discover "its next step", and must be helped to choose.
|
|
13
|
+
- **Context explosion** — Dumping everything upfront burns tokens and still doesn't help the agent understand what to do. Context must be handled as a scarce resource and therefore managed.
|
|
14
14
|
|
|
15
|
-
**
|
|
15
|
+
Ernesto creates a **tree structure** where agents naturally fall into the right bucket of tools and instructions based on their query. Workflows are engineered upfront, not improvised by the agent.
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
-
## The
|
|
19
|
+
## The Idea
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Ernesto helps an organization to kickstart its agentic tooling capabilities by incentivizing the curation of knowledge of any kind. The structure given to this knowledge: data, pre-established workflows, scripts etc... improves the performances of all kind of agents and therefore is always beneficial for the future operations of the organization. It also allows granular control over scopes (permissions), access, usage metrics...
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
execute(params, ctx) → { content: string, guidance: RouteGuidance[] }
|
|
25
|
-
```
|
|
23
|
+
Ernesto is an interface between humans, agents and systems. It naturally pushes stakeholders to build & maintain custom AI Workflows at the center of their organization, and to make them available to everyone (including agents).
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
The developer experience is at the center of the Ernesto system: developper's agent is naturally guided towards building itself thanks to strong layers of abstractions. It makes it easy for anyone from the organization to create and share his own workflows.
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
It can essentially be accessed in 2 ways:
|
|
28
|
+
- Native MCP: Experience on user's agentic client of choice (preferably Claude Code, OpenCode, Codex...)
|
|
29
|
+
- Wrapper API: Programmatically access Ernesto's capabilities by spawning agents connected to the MCP. It allows the creation of really polished experiences like Discord bots, Slack bots, Documentation Bot...
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
Because of his low overhead, Ernesto can be integrated (or integrate) easily: third-party clients, other MCPs etc... Making any kind of interface or connection only takes a few prompts.
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
prose: (i) => `View logs for ${i.user_id}`
|
|
42
|
-
},
|
|
43
|
-
fraud: {
|
|
44
|
-
when: (r) => r.riskScore > 80, // Only if high risk
|
|
45
|
-
route: 'redshift://tools/fincrime',
|
|
46
|
-
prose: (i, r) => `⚠️ Risk ${r.riskScore}! Investigate patterns`
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
export const investigateUser = createRoute({
|
|
51
|
-
route: 'redshift://tools/user-investigation',
|
|
52
|
-
description: 'Investigate user spending and risk patterns',
|
|
53
|
-
searchable: true, // Entry point (visible in search)
|
|
54
|
-
inputSchema: z.object({ user_id: z.string() }),
|
|
55
|
-
guidance,
|
|
56
|
-
|
|
57
|
-
async execute({ user_id }, ctx) {
|
|
58
|
-
const data = await queryDatabase(user_id);
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
content: formatMarkdown(data), // The answer
|
|
62
|
-
result: { riskScore: data.risk } // Data for guidance
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
});
|
|
33
|
+
## Two Operations
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
ask(query) Semantic discovery
|
|
37
|
+
Returns: searchable routes + matching resources
|
|
38
|
+
|
|
39
|
+
get(routes) Batch execution
|
|
40
|
+
Returns: { content, guidance } for each route
|
|
66
41
|
```
|
|
67
42
|
|
|
68
|
-
|
|
69
|
-
- Route is searchable → agent finds it via `ask("user fraud")`
|
|
70
|
-
- Executes, returns formatted analysis
|
|
71
|
-
- If risk > 80, unveils fraud investigation route
|
|
72
|
-
- Agent sees guidance, can drill deeper
|
|
43
|
+
Two operations that navigate an entire tree of organizational knowledge. The agent discovers the right branch, then follows guidance deeper until the task is complete.
|
|
73
44
|
|
|
74
45
|
---
|
|
75
46
|
|
|
76
|
-
##
|
|
47
|
+
## Core Concepts
|
|
77
48
|
|
|
78
|
-
|
|
79
|
-
|
|
49
|
+
The hierarchy forms a tree. Domains are branches. Searchable tools are entry points. Hidden tools are leaves you reach by following the path. Resources are indexed content from external sources and provide cached data in a shape of any kind (file system, database, API, etc...). They are discovered and agent is guided to load it.
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
Domain Branch of knowledge (warehouse, logs, translations...)
|
|
53
|
+
│
|
|
54
|
+
├─ Tool TypeScript-defined with execute()
|
|
55
|
+
│ ├─ Searchable Entry points agents discover via ask()
|
|
56
|
+
│ │ Return instructions + guidance to hidden tools
|
|
57
|
+
│ │
|
|
58
|
+
│ └─ Hidden Execution layer, unveiled contextually
|
|
59
|
+
│ Encode the actual business logic
|
|
60
|
+
│
|
|
61
|
+
└─ Resource Indexed content from external sources
|
|
62
|
+
(searchable via ask(), provides context)
|
|
63
|
+
```
|
|
80
64
|
|
|
81
|
-
|
|
65
|
+
When an agent asks about "revenue analysis," it lands in the warehouse domain, gets the analyst instructions, and is guided to simple server-side heavy revenue-specific tools: not lost in a sea of unrelated capabilities or too-versatile tools he will struggle to use.
|
|
82
66
|
|
|
83
67
|
---
|
|
84
68
|
|
|
85
|
-
##
|
|
69
|
+
## Agent Workflow
|
|
86
70
|
|
|
87
71
|
```
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
├── guidance.ts Guidance formatter
|
|
93
|
-
├── schema-formatter.ts Zod → human readable
|
|
94
|
-
│
|
|
95
|
-
├── Ernesto.ts Main orchestrator
|
|
96
|
-
├── domain.ts Domain builder
|
|
97
|
-
│
|
|
98
|
-
├── tools/ MCP tools (ask, get)
|
|
99
|
-
├── typesense/ Search & indexing
|
|
100
|
-
├── knowledge/ Content pipeline (extract docs → resources)
|
|
101
|
-
├── formats/ Content parsers (markdown, etc)
|
|
102
|
-
└── sources/ Content sources (filesystem, APIs)
|
|
72
|
+
1. ask("topic") → Semantic search finds the right domain
|
|
73
|
+
2. get([entry_point]) → Load instructions, receive guidance
|
|
74
|
+
3. get([unveiled_route]) → Execute with business logic baked in
|
|
75
|
+
4. Repeat until complete → Guidance chains to next steps
|
|
103
76
|
```
|
|
104
77
|
|
|
78
|
+
The agent doesn't improvise workflows: it follows paths your organization has already designed. Each tool knows what comes next and guides the agent there. This reduces the agent's job to **interpretation**: understand the query, follow the guided path, interpret results. That's a task LLMs excel at.
|
|
79
|
+
|
|
80
|
+
> "The agent should be gently pushed into knowing what to do because it was engineered upfront."
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Key Patterns
|
|
85
|
+
|
|
86
|
+
**Progressive Disclosure** — Tools revealed contextually via guidance. The tree structure means agents must load instructions before accessing execution tools: they can't skip steps or bypass business logic.
|
|
87
|
+
|
|
88
|
+
**Workflow-Optimized Tools** — Tools match mental models, not technical surfaces. "I want to investigate a user" not "POST /api/users/:id". One person solves a problem, documents it as a tool, and every agent can now follow that workflow.
|
|
89
|
+
|
|
90
|
+
**Cross-Domain Guidance** — A log investigation tool can suggest loading code-reading instructions. A user lookup can hint at invoice investigation tools. Domains connect to form complete workflows. This creates circles of discovery where the agent can navigate horizontally and not only top to down.
|
|
91
|
+
|
|
92
|
+
**Scope-Based Access Control** — Scopes cascade from domain → route → resource. Agents only discover and execute what their scopes allow. A support agent sees support tools; an admin agent sees admin tools. Access control is enforced at both `ask()` (discovery) and `get()` (execution).
|
|
93
|
+
|
|
94
|
+
**Server-Side Execution** — Templates run on server. Results render without entering agent context. This avoids loading complex queries into the agent, just create scripts and the agent runs them by calling the appropriate tool.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Primitives, Not Prescriptions
|
|
99
|
+
|
|
100
|
+
Ernesto is a thin coordination layer:
|
|
101
|
+
- **Extract**: Retrieve data from any source
|
|
102
|
+
- A git repo with gh
|
|
103
|
+
- Local File System
|
|
104
|
+
- Airbyte-like
|
|
105
|
+
- Custom Pipelines
|
|
106
|
+
...
|
|
107
|
+
|
|
108
|
+
- **Structure**: Shape this data as a...
|
|
109
|
+
- File System
|
|
110
|
+
- Typesense Collection
|
|
111
|
+
- Database
|
|
112
|
+
...
|
|
113
|
+
|
|
114
|
+
- **Search** — Discover relevant content using adequate tools for the structure chosen
|
|
115
|
+
- **Execute** — Allows the agent to execute commands discovered.
|
|
116
|
+
|
|
105
117
|
---
|
|
106
118
|
|
|
107
|
-
##
|
|
119
|
+
## Quick Example
|
|
120
|
+
|
|
121
|
+
### Domain Definition
|
|
108
122
|
|
|
109
123
|
```typescript
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
searchable: false,
|
|
116
|
-
inputSchema: z.object({ sql: z.string() }),
|
|
117
|
-
execute: async ({ sql }, ctx) => contentOnly(
|
|
118
|
-
await runQuery(sql)
|
|
119
|
-
)
|
|
124
|
+
const warehouseDomain: DomainDefinition = {
|
|
125
|
+
name: 'warehouse',
|
|
126
|
+
description: 'Data warehouse access - query orders, users, analytics',
|
|
127
|
+
requiredScopes: ['analytics'], // Only agents with 'analytics' scope can access
|
|
128
|
+
tools: [analystTool, queryTool, userInvestigationTool],
|
|
120
129
|
};
|
|
121
130
|
```
|
|
122
131
|
|
|
123
|
-
|
|
132
|
+
### Searchable Tool (Entry Point)
|
|
124
133
|
|
|
125
|
-
|
|
134
|
+
The entry point teaches the agent about this domain and guides it to the right execution tools.
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
const analystTool: ToolDefinition = {
|
|
138
|
+
route: 'warehouse://tools/analyst',
|
|
139
|
+
name: 'Warehouse Analyst',
|
|
140
|
+
description: 'Intelligent analyst with schema knowledge',
|
|
141
|
+
searchable: true,
|
|
142
|
+
|
|
143
|
+
async execute(params, ctx) {
|
|
144
|
+
return {
|
|
145
|
+
content: `## Warehouse Guide\n\nAvailable tables: fact_orders, dim_user...\n\nFor revenue questions, use revenue-breakdown. For user investigations, use user-investigation.`,
|
|
146
|
+
guidance: [
|
|
147
|
+
{ route: 'warehouse://tools/hidden/query', prose: 'Execute custom SQL' },
|
|
148
|
+
{ route: 'warehouse://tools/hidden/user-investigation', prose: 'Deep-dive on a user' },
|
|
149
|
+
{ route: 'warehouse://tools/hidden/revenue-breakdown', prose: 'Revenue analysis by period' },
|
|
150
|
+
],
|
|
151
|
+
};
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
```
|
|
126
155
|
|
|
127
|
-
|
|
156
|
+
### Hidden Tool (Unveiled via Guidance)
|
|
157
|
+
|
|
158
|
+
Hidden tools encode the actual execution. The agent only reaches them after loading context.
|
|
128
159
|
|
|
129
160
|
```typescript
|
|
130
|
-
|
|
161
|
+
const queryTool: ToolDefinition = {
|
|
162
|
+
route: 'warehouse://tools/hidden/query',
|
|
163
|
+
name: 'SQL Query',
|
|
164
|
+
description: 'Execute SQL against the warehouse',
|
|
165
|
+
searchable: false, // Only accessible after loading analyst instructions
|
|
166
|
+
requiredScopes: ['sql-write'], // Additional scope for raw SQL (inherits 'analytics' from domain)
|
|
167
|
+
|
|
168
|
+
async execute(params, ctx) {
|
|
169
|
+
const result = await warehouseClient.query(params.sql);
|
|
170
|
+
return {
|
|
171
|
+
content: formatAsMarkdown(result),
|
|
172
|
+
guidance: [
|
|
173
|
+
{ route: 'logs://tools//search-logs', prose: 'Continue investigation with logs' }, // Cross Domain Guidance
|
|
174
|
+
],};
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
```
|
|
131
178
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
179
|
+
### Resource (Cached Data)
|
|
180
|
+
|
|
181
|
+
Resources provide indexed, searchable content. They're discovered via `ask()` and loaded on demand—keeping context lean until the agent actually needs it. Tools can provide guidance to discover and use them. Native MCP Templates Resources can be used.
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
const schemaResource: ResourceDefinition = {
|
|
185
|
+
route: 'warehouse://resources/schema-docs',
|
|
186
|
+
name: 'Schema Documentation',
|
|
187
|
+
description: 'Table schemas, column descriptions, usage examples',
|
|
188
|
+
|
|
189
|
+
async fetch(ctx) {
|
|
190
|
+
return {
|
|
191
|
+
content: await loadFromCache('schema-docs'),
|
|
192
|
+
};
|
|
193
|
+
},
|
|
194
|
+
};
|
|
137
195
|
```
|
|
138
196
|
|
|
139
|
-
|
|
197
|
+
Resources decouple content from execution. The agent discovers relevant documentation, loads cached context, and uses it to drive tool execution—without burning tokens on upfront context dumps.
|
|
140
198
|
|
|
141
199
|
---
|
|
142
200
|
|
|
143
|
-
|
|
201
|
+
### The Flow
|
|
144
202
|
|
|
145
|
-
|
|
203
|
+
The agent's query lands it in the right domain. Instructions guide it to the right tool. No guessing.
|
|
146
204
|
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
205
|
+
```
|
|
206
|
+
Agent: ask("how many orders yesterday")
|
|
207
|
+
↓
|
|
208
|
+
Ernesto: Returns warehouse://tools/analyst (semantic match)
|
|
209
|
+
↓
|
|
210
|
+
Agent: get([{ route: "warehouse://tools/analyst" }])
|
|
211
|
+
↓
|
|
212
|
+
Ernesto: Instructions + guidance → unveils hidden/query
|
|
213
|
+
↓
|
|
214
|
+
Agent: get([{ route: "warehouse://tools/hidden/query", params: { sql: "..." } }])
|
|
215
|
+
↓
|
|
216
|
+
Ernesto: Query results (workflow complete)
|
|
154
217
|
```
|
|
155
218
|
|
|
156
|
-
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Installation
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
npm install ernesto
|
|
225
|
+
```
|
|
157
226
|
|
|
158
227
|
---
|
|
159
228
|
|
|
160
|
-
##
|
|
229
|
+
## Contribute
|
|
161
230
|
|
|
162
|
-
|
|
231
|
+
> Read README.md and discover the Ernesto system.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
## Reference
|
|
235
|
+
|
|
236
|
+
See [REFERENCE.md](./REFERENCE.md) for implementation specs:
|
|
237
|
+
|
|
238
|
+
- Route URIs and type hierarchy
|
|
239
|
+
- `ask()` and `get()` internals
|
|
240
|
+
- Progressive disclosure flow diagrams
|
|
241
|
+
- Content extraction pipeline
|
|
242
|
+
- Scope-based access control
|
|
243
|
+
- Tool patterns and lifecycle management
|
|
244
|
+
|
|
245
|
+
---
|
|
163
246
|
|
|
164
|
-
|
|
247
|
+
*Ernesto: Making organizational knowledge accessible to AI agents through progressive disclosure.*
|