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 CHANGED
@@ -1,164 +1,247 @@
1
- # Ernesto Lib
1
+ # Ernesto
2
2
 
3
- ## How It Works (and Why)
3
+ A context system that structures organizational knowledge and makes it accessible efficiently to AI agents.
4
4
 
5
- **The Problem:** Give an AI agent 50 tools and it gets paralyzed by choice. Give it 3 tools and it can't solve complex problems.
5
+ ---
6
+
7
+ ## The Problem
6
8
 
7
- **The Solution:** Progressive disclosure. Start with a few searchable entry points. Each route reveals relevant next steps based on what it finds.
9
+ Traditional approaches to AI agent tooling fail at scale:
8
10
 
9
- **Example flow:**
10
- 1. Agent searches `"user fraud investigation"` finds `redshift://tools/user-investigation`
11
- 2. Executes route, gets user data showing high risk score
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
- **Why this works:** Tools appear when contextually relevant, not all upfront. The agent builds a workflow by following breadcrumbs, not by choosing from a haystack.
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 Pattern
19
+ ## The Idea
20
20
 
21
- Every route does one thing:
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
- ```typescript
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
- That's it. Return markdown content, optionally unveil next routes via guidance.
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
- ## Quick Example
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
- ```typescript
34
- import { createRoute, defineGuidance } from 'ernesto/lib/route';
35
-
36
- // Define conditional guidance based on results
37
- const guidance = defineGuidance<Input, Result>({
38
- logs: {
39
- always: true, // Always suggest this
40
- route: 'app-logs://tools/user-activity',
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
- **What happens:**
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
- ## Two Visibility Levels
47
+ ## Core Concepts
77
48
 
78
- - **`searchable: true`** Entry points. Always in `ask()` results.
79
- - **`searchable: false`** — Hidden. Only unveiled via guidance from other routes.
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
- This creates guided workflows instead of tool chaos.
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
- ## File Structure
69
+ ## Agent Workflow
86
70
 
87
71
  ```
88
- lib/
89
- ├── route.ts Route builders (createRoute, defineGuidance)
90
- ├── types.ts Core types (Route, GuidedContent)
91
- ├── router.ts Execution engine
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
- ## Simple Route (No Guidance)
119
+ ## Quick Example
120
+
121
+ ### Domain Definition
108
122
 
109
123
  ```typescript
110
- import { contentOnly } from 'ernesto/lib/route';
111
-
112
- export const simpleRoute: Route<Input> = {
113
- route: 'domain://tools/query',
114
- description: 'Run a database query',
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
- Use `contentOnly()` when you don't need guidance.
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
- ## Building a Domain
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
- import { createDomain } from 'ernesto/lib/domain';
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
- export const myDomain = createDomain({
133
- name: 'my-domain',
134
- description: 'What this domain does',
135
- routes: [route1, route2, route3]
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
- Register it in `src/ernesto/domains/index.ts`.
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
- ## Content Pipeline (Optional)
201
+ ### The Flow
144
202
 
145
- Index external content as searchable resources:
203
+ The agent's query lands it in the right domain. Instructions guide it to the right tool. No guessing.
146
204
 
147
- ```typescript
148
- {
149
- extractors: [{
150
- source: new LocalSource('docs/'),
151
- format: new MarkdownFormat({ split: true })
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
- **Source** (WHERE) + **Format** (HOW) → Resources → Indexed → Searchable
219
+ ---
220
+
221
+ ## Installation
222
+
223
+ ```bash
224
+ npm install ernesto
225
+ ```
157
226
 
158
227
  ---
159
228
 
160
- ## That's It
229
+ ## Contribute
161
230
 
162
- One pattern. Two visibilities. Guided discovery.
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
- Build routes that unveil routes. Let the agent follow the breadcrumbs.
247
+ *Ernesto: Making organizational knowledge accessible to AI agents through progressive disclosure.*