Etienne is an integration harness around a coding harness to build user friendly agent interactions:
Etienne showcases how to attach typical business requirements to a coding agent harness in order to enable a non-technical user to interact with the agent using a refined UI.
This setup addresses the use case business collaborator agent working on local data.
The user interface is available for these languages:
- English (US)
- German (DE)
- Chinese (mandarin)
Etienne's UI is build around role based access control with these basic roles (can be enhanced):
Etienne uses different roles to have clear responsibilities defined - it is usually NOT deployed as a personal AI assistant where the admin and the user role would be the same person.
The following comparison illustrates the conceptual differences between Etienne and OpenClaw as of early 2026:
Etienne guides the business user to do proper context engineering. In the background it carefully balances the main context components to avoid context window overflow:
One of the most important strategies is to think in isolated and scoped projects - this allows to adjust for example the selected skills to the current user problem and makes it easy to "forget" (just delete the folder).
An agent is more "intelligent" if it has a notion of its own environment. For this reason there's a world model skill which is required for scenarios like self-healing or coding projects. In the first scenario this skill prevents the agent from endless codebase analysis and guides it directly to the closest location, in the second scenario this skill prevents the agent from recreating already existing infrastructure like the RDF store.
Here are the guiding principles for Etienne, and why I believe it matters:
Focused on usability and simplicity. I build it because I like to use it myself. And one day, I might build an entirely different business on top of it. If the builder doesn't enjoy the tool, nobody will.
Aware of its place in a bigger world. Etienne doesn't try to be everything. It's designed to run inside an agentic OS — something like OpenAI Frontier — which handles all the infrastructure burdens I don't want to reinvent: prompt injection detection and prevention, data access policies, audit trails for compliance. Etienne is the agent experience layer. The platform handles the plumbing.
Deterministic where it counts. Here's the quiet revolution: Etienne introduces traditional control mechanisms into the agentic world. CRON jobs for scheduling. Finite state machines for workflows. Ontology graphs for knowledge acquisition. Decision graphs built on top of those ontologies. An internal agent event bus combined with external triggers — email, MQTT, webhooks.
Isolated by design. Every task lives inside a project. Knowledge graphs, decision graphs, workflows, data — all of it is scoped to a defined mission statement. No bleed. No confusion. No agent accidentally applying restaurant marketing logic to your medical practice.
Composable everywhere. Use standard agent skills to enhance process knowledge. Use MCP tools to enhance data access. Use file previewers and editors to let users manipulate complex results directly — modifying a CAD object, controlling a robot, reviewing a financial model. The agent doesn't just produce output. It produces editable output.
Built for continuous improvement. Project-level knowledge graphs and decision graphs can be promoted to the company level — managed as Microsoft Fabric IQ objects and rules. Agent skills developed in one project can be submitted to an administrator for review, then published to a local skill store, making them available to every other user. The system learns. Not in the fuzzy, hand-wavy way that LLMs "learn." In the structured, auditable, improvable way that actual organizations need.
Respectful of security. Etienne provides a role-based access control core around APIs and UI, adaptable to any existing identity management system — EntraID, Okta, whatever your company already runs. It supports Git-controlled versioning, backup and restore, and defined releases aligned to basic compliance rules. Event logs and settings live in defined, inspectable, auditable places. Your IT department won't love it on day one. But they won't block it either.
- Built for Artifacts
- Built around Skills
- Built for Connectivity
- Focused on local Data and Services
- Self-Healing Capabilities
- Supported Coding Models
- Multi-agent Orchestration
- Managed Etienne
- Memory
- The Web: searching, scraping and browsing
- Main Components
- The Agent and the outside World
- Securing the Agent against Prompt Injection
- IT Budget Situation
- Extended Use Case: Prototyping together with your Customer
- Demo Videos
- Etienne Articles on LinkedIn
- Setup
- User Authentication in the Frontend UI
- API Endpoints
- Knowledge Base Feature
- Context Management / Metadata Layer
- Observability
- Spec-driven Development
- File Type Previewers
- Messenger Integration
- MCP UI
- Budget Tracking
- Maintainer
Of of the most valuable UI features is to work side by side with the agent on complex results (=artifact).
Many configurator or data exploration use cases greatly benefit from this kind of workflow:
- Describe your problem in the chat pane
- AI agent generates first draft and presents it in the artifacts pane
- User refines draft either by clicking directly on a detail in the artifacts pane OR by asking the agent to make the change
This main collaboration feature sets Etienne apart from other agents like OpenClaw, which is focused on a command/execution pattern via a simple messenger user interface.
This isn't science fiction. This is skill-based AI agent development, and it's about to change how your organization works with AI. What's even better: Agent Skills work across vendors. So if you later switch from an OpenAI-based solution to an Anthropic-based one — or any other provider — your investment in skills is preserved. No lock-in. No starting over.
At its core, an agent skill is just two things working together:
- A markdown file written by a business expert — describing what to do, when to do it, and why it matters, in plain language anyone can read and understand.
- Code snippets (Python, JavaScript, or any language) contributed by an IT engineer — providing the technical muscle to execute that expertise.
That's it. Business knowledge meets technical capability in a single, portable folder.
When a user describes their task, the agent doesn't just process words — it recognizes which skill matches the situation, loads the relevant business expertise, and seamlessly translates the user's intent into the right technical execution. The business expert's judgment guides the engineer's code. The result? AI that doesn't just respond — it understands your business.
This is where things get exciting. Let me walk you through how this works in practice with Etienne:
An administrator curates skills — either building them from scratch with domain experts or selecting proven ones from a shared repository. Every skill is security-checked and technology-approved before it enters the company's skill store.
Business users browse the approved skill catalog and select the ones relevant to their current project. The skill is copied into their project directory. No installation headaches. No waiting on IT tickets. Self-service, but with guardrails.
From this point on, the agent automatically applies the skill whenever the user's task calls for it. The user focuses on their work; the agent handles the expertise-to-technology translation behind the scenes.
Here's where the magic happens: as the agent works within a project, it can refine and improve the skill based on real-world usage. A generic "financial report analysis" skill might become a finely tuned "Q3 EMEA margin analysis" skill — adapted to the user's actual needs. At this point, it truly becomes the user's skill.
When a user discovers that their refined skill is significantly better, they can submit it back to the IT administrator. The admin reviews the changes, validates them, updates the central repository — and suddenly, every team in the organization can benefit from one user's practical discovery.
This is agentic learning with human supervision at its best.
Let's be clear about what this lifecycle delivers:
- Understandable. Skills are expressed in markdown. Not in opaque model weights. Not in mysterious embeddings. In plain language that any business stakeholder can read, review, and challenge. When your compliance team asks "what does the AI actually do?" — you hand them the skill file.
- Battle-tested. Every improvement comes from a real user solving a real problem in a real project. This isn't theoretical optimization. It's field-proven refinement.
- Intentional. Skill updates don't happen silently in the background. A user consciously decides to submit an improvement. A human makes the choice.
- Reviewed. The four-eyes principle applies. An admin reviews every submitted change before it enters the repository. No unvetted modifications reach other users.
- Safe to deploy. Updated skills don't retroactively change existing results in a user's project. The rollout is safe because users must opt-in to updates through their project settings. Think of it as software updates — only on a higher abstraction level.
Behind the scenes, administrators have access to a Skills Store — a management interface where they oversee the entire skill portfolio. Each skill carries rich metadata that goes beyond the open standard, allowing companies to define their own strategies for evolving, versioning, and distributing skills across the organization.
Etienne also adds practical extensions to the formal standard that business environments demand:
- Technical dependencies — a clear list of system requirements (npm packages, Python libraries, or other artifacts) that must be present on the agent's host system. No guesswork about what needs to be installed.
- Environment variables — explicit declarations of which API keys, tokens, or configuration values the skill needs. After installing a skill, a user can securely provide their personal credentials scoped exclusively to their project.
This means IT knows exactly what a skill requires before deployment, and users maintain control over their own credentials and configurations.
The Integrated AI Agent Architecture connects three existing systems through a shared ZeroMQ event bus, enabling a perceive → contextualize → decide → act → remember agent loop.
| System | Role | Metaphor |
|---|---|---|
| CMS (Event-Handling) | Sensory Layer | Eyes & ears — perceives what's happening now |
| DSS (Ontology-Core) | Memory & Reasoning | Brain — stores knowledge, provides context |
| SWE (Stateful-Workflows) | Motor Layer | Hands — executes deliberate multi-step actions |
| Agent Bus | Nervous System | Connects all components via messages |
graph TB
subgraph "External Event Sources"
IMAP[Email / IMAP]
MQTT[MQTT Devices]
WH[Webhooks]
FS[File System]
TIMER[Schedulers]
end
subgraph "CMS — Condition Monitoring System"
ER[EventRouterService]
RE[RuleEngineService]
RAE[RuleActionExecutorService]
end
subgraph "Agent Bus"
EB[EventBusService<br/>ZeroMQ PUB/SUB]
IR[IntentRouterService]
DQA[DssQueryAdapterService]
CI[ContextInjectorService]
BL[BusLoggerService]
end
subgraph "DSS — Decision Support System"
DSS[DecisionSupportService]
KG[KnowledgeGraphService<br/>Quadstore RDF]
VS[VectorStoreService<br/>ChromaDB]
end
subgraph "SWE — Stateful Workflow Engine"
SWS[StatefulWorkflowsService<br/>XState v5]
WEA[WorkflowEntryActionService]
end
IMAP & MQTT & WH & FS & TIMER --> ER
ER -->|"events/raw/*"| EB
ER --> RE
RE -->|rule matched| RAE
RAE -->|"agent/intent"| EB
RAE -->|"prompt action"| LLM[Claude LLM]
RAE -->|"workflow_event"| SWS
EB -->|"agent/intent"| IR
IR -->|"workflow/trigger"| EB
EB -->|"workflow/trigger"| SWS
SWS -->|"workflow/status/*"| EB
SWS --> WEA
WEA -->|prompt/script| LLM
DQA --> DSS
CI --> DQA
RAE -.->|enrich| CI
WEA -.->|context| CI
DSS --> KG
DSS --> VS
EB -->|"dss/update"| DSS
EB -->|"dss/query"| DQA
EB --> BL
style EB fill:#f9a825,stroke:#f57f17,color:#000
style BL fill:#e8f5e9,stroke:#43a047
Etienne's data structures are build around the idea of keeping things local and separated. This might be a strange concept of self-containment if you are a cloud developer and your daily-business is dealing with shared services like databases.
Etienne expects all the user data inside a single local workspace directory (or in case of Docker deployment a single mount). The subdirectories in the workspace are the projects.
While in advanced use cases the agent can work cross-project the default setting for the coding agent's root directory is set at project level.
Inside the workspace the usual . convention applies: The user cannot see any internal files or directories starting with a . character.
Only the admin role can see these files via the UI:
All relevant settings and data are kept on project level to ensure two features:
- Right to forget if sensitive data was processed inside one project, it will be purged when the directory is deleted
- Portability users can exchange a complete project by simply copying the directory
The user interface provides access to the process-manager API which is responsible of starting/stopping local servers on different ports.
This feature is not so much targeted at human usage, but to give the agent the ability to decide which services to ramp up: There is an MCP server with a MCP App(UI) which enables the user to access service control also in the chat pane.
All of the local services treat projects like tenants: they store their data (also temp files) in subdirectories of the project folder and serve them from this location.
In the example above we can see the RDF store ("knowledge graph") log and data files inside a project's directory.
As this project is built around the most sophisticated coding harness, one feature comes to your mind quite immediatelly: "Can't the agent fix its own code when there's some kind of error?"
Not every error is an error though - this is why we should add a proper safeguard by using the human 4 eyes principle: No code part of the vital agent functionalities should be fixed automatically!
Etienne gives our agent the ability to patch its own source code when you report problems — with full human oversight at every critical step. You can open the issue tracker from the project menu:
Here's the workflow: A user files an issue describing what's broken. An admin reviews it, sets priority, and authorizes the AI agent to investigate. Because the data (which probably caused the error) is still in the project directory, the agent — Claude Opus 4.5 via the Claude Agent SDK — can directly analyze data, source code, logs, and configuration "in-place", it can identify the root cause, and can create a minimal code patch. Depending on the risk level, the patch is either applied automatically or presented to the admin for review. After patching, the affected service restarts and the system verifies the fix worked. If it didn't, automatic rollback kicks in.
sequenceDiagram
actor User
actor Admin
participant Agent as AI Agent<br/>(Claude Opus 4.5)
participant System as Application
User->>Admin: File issue (bug report)
Admin->>Admin: Review & set priority
Admin->>Agent: Authorize investigation
Agent->>System: Analyze source code, logs & config
Agent->>Agent: Identify root cause
Agent->>Agent: Generate minimal patch
alt Low risk
Agent->>System: Apply patch automatically
else High risk
Agent->>Admin: Present patch for review
Admin->>Agent: Approve / reject
Agent->>System: Apply approved patch
end
System->>System: Restart affected service
System->>System: Run verification checks
alt Verification passed
System-->>Admin: Fix confirmed
else Verification failed
System->>System: Automatic rollback
System-->>Admin: Rollback notification
end
This is not a copilot suggesting changes for you to implement. This is an embedded repair system that lives inside our agent, understands our code at the deepest level, and acts on explicit human authorization.
Four safety layers ensure you're always in control:
- Admin approval gates — no agent action starts without explicit authorization
- Agent-level guardrails — dangerous commands blocked, file edits restricted to the application directory
- Pre-patch snapshots with automatic rollback on verification failure
- Immutable audit trail — every agent action is logged (who approved, what changed, what happened)
Graduated autonomy lets admins build trust incrementally across four levels: from observe-only (Level 0) where the agent only diagnoses and suggests fixes, to fully automatic patching with rollback guarantees (Level 3). New deployments always start at Level 0.
sequenceDiagram
participant Agent as AI Agent
participant FS as Filesystem
participant Snapshot as Snapshot Store
participant Service as Affected Service
participant Verify as Verification
Agent->>FS: Identify files to patch
Agent->>Snapshot: Create pre-patch snapshot
Snapshot-->>Agent: Snapshot ID saved
Agent->>FS: Apply code patch
Agent->>Service: Restart service
Service-->>Verify: Service running
Verify->>Verify: Run health checks & tests
alt All checks pass
Verify-->>Agent: Verification OK
Agent->>Agent: Log success to audit trail
else Checks fail
Verify-->>Agent: Verification FAILED
Agent->>Snapshot: Retrieve snapshot
Snapshot-->>Agent: Original files
Agent->>FS: Restore from snapshot
Agent->>Service: Restart service (rollback)
Agent->>Agent: Log rollback to audit trail
end
The immune system most other agents lack — with a human hand on the switch.
To enable self-healing on a project, activate the self-healing skill from the skill store. It guides users through creating structured issue reports with title, description, reproduction steps, and expected vs. actual behavior — all submitted to an admin for review before any automated repair is triggered.
Though Etienne was initially implemented for the Anthropic Claude Agent SDK you can use other (coding) models by setting the CODING_AGENT variable in the .env file in the backend:
The main drawback with other models is limited support for MCP tools or agent skills which becomes obvious with more complex agentic tasks.
Multi-agent orchestration is currently only supported if CODING_AGENT=anthropic is set for the backend. In this case you can define subagents in the project menu:
The Claude Agent SDK will pick up those agents and run them in parallel or in sequence whenever it detects tasks might benefit from doing so. Your subagents will be used additionally to the built-in Claude agents.
Codex AppServer does not support orchestration though it can use and understand a subagent definition. As of early 2026 the MacOS Codex App is responsible for orchestration of several AppServer instances.
You can install Etienne locally, deploy it using the Docker (after you have built it from Docker the file provided) or get it hosted on AWS:
Etienne provides an exchangable endpoint to extract memories from a user prompt and store them inside the project.
Memory extraction is activated per default and can be accessed via the green memory card icon below the app bar.
Memories are stored per project and not globally in the default configuration.
The extraction prompt is adjustable to sharpen the focus to certain business domain relevant information.
Use the web-scraping skill to enable the agent to interact with websites on the internet.
It uses these technologies by default:
-
Web search: The default tool included in Claude Code or Codex. Uses the search index of Anthropic or OpenAI.
-
Web scraping: Uses the Scrapling GitHub project which is fast and can process Javascript sites. It is a common choice for red-teaming tasks.
-
Web browsing: Uses Vercel's agent-browser package, a headless browser automation CLI designed for AI agents. Pre-installed in the Docker image via
npm install -g agent-browserwith Chromium pre-downloaded. It is a good choice for cooperative sites and a token saver (compared to pure Playwright implementations). The browser daemon can be managed from the service console. Keep in mind that it is not suited to interact with websites which deploy anti-bot/anti-agent techniques like captchas or fingerprinting!
This repo contains 3 mandatory servers, 6 optional servers and many modules.
Modules can be removed if their functionality is not required (e. g. A2A Client, Observability, SMTP IMAP).
The following diagram shows the essential internal and external ports of a deployed Etienne instance:
While the workbench (React frontend) serves as the primary user interface, messengers can optionally be added as secondary/mobile user interfaces.
Etienne is built to maximize what an AI agent can do outwardly in commercial and operational contexts.
Etienne focuses on professional automation protocols in a single deployment, which is what commercial environments actually run on.
Etienne extends the system boundary itself by implementing and exposing new interfaces such as MCP servers, API endpoints, or web applications.
Etienne is about turning an agent into infrastructure.
Prompt injection is the #1 security threat to AI agents right now.
When Etienne connects to tools and databases, every user input becomes a potential attack. Malicious prompts can trick it into leaking data, bypassing safety rules, or executing unintended actions.
The solution: A security gateway that sits between users and our AI models.
It scans every request real-time, blocking attacks before they reach your systems. Simple concept, but here's the reality most vendors won't share:
Security isn't a one-time fix. New attack patterns emerge daily.
Effective protection requires: ✅ Always-on cloud infrastructure (for speed) ✅ Continuous threat updates (not static rules) ✅ Active learning (adapting to new risks)
This means your security layer becomes a complex system itself. But that's the cost of staying protected.
Start your security journey with understanding these services:
- NeuralTrust API Gateway
- Google ModelArmorAPI
- AWS Bedrock Guardrails
This project is in the middle between "Buy a complete AI agent solution" and "Build an AI agent framework from scratch". You should extend/modify it using Claude Code.
It proposes to focus your development efforts on the business layer instead on the AI layer.
As a forward deployed engineer you can bring a complete working AI business solution to the meeting with your customer. The Etienne frontend in combination with Claude Code for live modifications allows you to prototype solutions in real-time.
Watch Etienne walking the user through a mindmap creation process
See the basic project settings and how a live website is created from specifications
The feature is all about testing a specific hypothesis:
Can you go from a business requirement to a deployed, fully customized AI system — without writing a single line of application code?
The answer, at least for a certain class of software, appears to be yes. Here's the five-step process we used:
- Step 1 — Business Requirements Document We sat down with the customer and wrote a concept document the way you'd write any product spec: what problem are we solving, for whom, what does the system do, what does it explicitly not do. Plain language. No code. The document also contained the marketing narrative, the pricing model, and a detailed technical architecture — written in prose, not pseudocode.
Read the Document (.docx) here
-
Step 2 — Agentic OS Creates the Agent-Description-Package We gave that document to a general-purpose AI agent — one that has been taught its own architecture: how RDF Knowledge Graphs work, what a RAG pipeline is, how SPARQL queries are structured, what cron governance means. Because the agent understands itself, it could read the concept document and generate a complete Agent-Description-Package (ADP): a ZIP file containing every artifact the final system would need:
-
System prompts for each sub-agent.
-
Configuration files.
-
Governance rules.
-
An onboarding checklist.
-
A machine-readable MANIFEST.json with install order and integrity hashes.
The agent specified itself.
-
Step 3 — Generic Agent Receives ADP and Transforms Itself A separate instance of the general-purpose agent — no product knowledge, no pre-built application — receives the ZIP. It reads MANIFEST.json, validates the contents, and uses its own code generation and configuration capabilities to instantiate the system described in the ADP. This is not running an installer. This is an agent becoming what the specification describes. Self-adaptation from a description package. Note: Etienne is a integration harness around a coding harness like Claude Code or Codex - so it has extensive software implementation knowledge.
-
Step 4 — Onboarding: Agent Meets Customer The newly instantiated agent begins its onboarding phase autonomously. It introduces itself, conducts a structured interview, and actively requests the materials it needs: supplier lists, order history, contracts, org charts, anything that will prime its knowledge systems. It doesn't stop until every item on the onboarding checklist — embedded in the ADP — is fulfilled. The checklist is the agent's own definition of "ready."
-
Step 5 — Work Cycle with Human-in-the-Loop Once onboarded, the agent begins its operational cycle. It monitors, reasons, drafts, warns — and surfaces every consequential action to a human approval queue before acting. The human stays in control. The agent gets better with every correction.
Decision support is one of the most advanced features of Etienne. You must start the Knowledge Graph and the Vector Store services before you will be able to use it:
Additionally the decision-support skill needs to be activated on your project:
Then open the decision support studio window from the project menu:
Currently you have to add entity instances manually using "+ Add Entity":
|
Ontologies, Agents, and the Art of Knowing What to Do
There's a concept buried inside Palantir Foundry that most people never talk about. They talk about the data integration. The pipelines. The price tag. But the genuinely interesting idea — the one that separates Foundry from a very expensive data warehouse — is something called the Ontology core. And once you understand it, you'll never look at AI agents the same way. |
|
Formal Guarantees vs. Flexible Composition: Choosing the Right AI Workflow Architecture
Welcome to the great AI architecture debate of 2026: LLM Event Loops vs. Hierarchical Agent Trees vs. Finite State Machines. Three approaches. Three different answers to the same question: Who should control your workflow - your LLM, your code, or a formal state machine? |
|
Why Your AI Agent's Compliance Process Might Be Your Secret Competitive Advantage
Etienne takes a different approach. Instead of treating compliance as the annoying thing you do after building something cool, it treats your requirements document as the single source of truth from day one. |
|
From Chatbots to Colleagues: RBAC and Engineered Context as the Missing Layer
Etienne is designed as a professional collaborator inside a company environment. It operates on private files, inside a workspace that is subdivided into projects, and assumes a clear separation between technical stewardship and business usage. That separation is enforced through RBAC and amplified through deliberate context engineering. |
|
Building Etienne: How We Turned Claude Code 2.0 into an AI Agent Platform
Anthropic wants to build something that sounds like science fiction: a virtual colleague that actually works like a real teammate - thinking through complex problems, remembering bad ideas to avoid them in the future, making decisions based on your private data, and getting things done over hours or days, not seconds. |
![]() |
Understanding Etienne: Complementing Claude Agent SDK's Agentic Loop
In my previous article, I illustrated how you can leverage Claude Code's agentic loop by attaching it to your own user interface and business logic. Basically: "Here's how to get the engine running." But here's the thing nobody tells you about AI agents: Getting them to work is easy. Getting them to work in production requires solving a dozen unsexy problems that have nothing to do with AI. |
![]() |
Feeding Etienne: Condition Monitoring with AI Agents
Picture this: It's Monday morning, and somewhere in Hamburg, a businessman named Thomas is still in his bathrobe, sipping coffee while his AI agent named Etienne is already hard at work. Not because Thomas programmed it to start at 6 AM, but because the world started talking to it - and Etienne was hungry. |
![]() |
Etienne's Scrapbook: How to transform Human Intent into Agentic Attention
This article describes how to move beyond single prompts to orchestrate complex, multi-faceted projects with AI agents. |
![]() |
Etienne is getting picky: Why 90% of Production AI Agent Systems Are Basically Expensive Random Number Generators
Context failures have overtaken model failures as the primary cause of AI agent breakdowns. After analyzing production systems from Anthropic, Google, and leading AI engineering teams, one pattern emerges: the quality of your context management directly determines agent reliability. |
![]() |
Etienne's Memories: How Claude Agent SDK AI Agents Build Knowledge Over Time
Anthropic didn't call it "Agentic Learning"—but they built something arguably more sophisticated. In October 2025, the company unveiled a distributed, file-based learning system that enables Claude to accumulate expertise across sessions, projects, and entire organizations. This architecture combines hierarchical memory files, on-demand skill loading, persistent task tracking, and iterative error correction into what may be the most practical approach to AI agent learning yet developed. |
![]() |
How Etienne Solves AI's Last Mile Problem: Bringing AI to Where the Data Lives
The world's most valuable data - patient records, proprietary algorithms, classified research, industrial secrets - sits locked behind security perimeters where cloud AI can never reach. Even when data access isn't restricted, professional workflows demand AI that understands specialized artifacts like DICOM scans, financial models, and CAD drawings—not generic file processors that treat domain expertise like raw text. |
![]() |
Etienne after Dark: How A2A accidentally started an AI Rave
As a general AI agent, Etienne could reason, plan, decompose tasks, and orchestrate workflows all day long. But the real world doesn’t run on reasoning alone. It runs on invoices, shipping quotes, compliance checks, pricing engines, calendars, databases, and services with very specific opinions about how things should be done. So Etienne did what any competent orchestrator would do: it stopped pretending to be everything and started calling specialists. |
![]() |
Dressing Up Etienne: How to integrate AI Agents with your Customer's Business Workflows
Many AI agent projects crash and burn when they meet the harsh reality of real-world implementation. What looked brilliant in an isolated demo gets rejected faster than a soggy sandwich – either by employees frustrated with poor usability or IT teams pulling their hair out over integration nightmares. This article walks you through a step-by-step approach to successfully weaving AI agents into your customer's existing technical and organizational fabric - based on my 20 years experience in enterprise consulting. |
![]() |
Swipe Right on Smart Agents: Etienne's Guide to Digital Romance with Real-World Data
Meet Etienne - not your typical bachelor, but an open-source AI agent build with Anthropic's Agent SDK who's about to get hitched to the real world! Unlike those chatbots that live in isolation, Etienne knows how to mingle at the party, check his calendar, and even remember where he put his keys. So join the wild data party with Etienne and his hangover buddy Claude! |
![]() |
Fearing Etienne: How Forward-Deployed GenAI Engineers Will Replace Consulting and Software Development Teams
The traditional consulting-to-development pipeline is dead. One forward-deployed engineer with the right AI toolbox can deliver production systems in a few days. This article explores the forward-deployed engineer's secret weapon: exploiting AI systems' ability to self-reproduce while adapting to any business domain. |
![]() |
Etienne Everywhere: Using Telegram and Microsoft Teams as an Alternative UI
That’s why Etienne supports messengers as an alternative UI - specifically Telegram and Microsoft Teams. Etienne is represented by a bot in both messengers. |
![]() |
Onboarding Etienne: The Next Best Thing to a Pip-Boy until the Nukes drop!
This article introduces the first steps with Etienne: an open-source seed project built on the Anthropic Agent SDK. Etienne is a personal, fully customizable agentic system that runs close to your data and depends only on an AI model exposing an Anthropic-compatible message API. No platform lock-in. No mandatory cloud brain. Just an agent you can actually own. |
![]() |
Diagnosing Etienne: Inside the Black Box of AI Agent Behavior
AI agents no longer solve problems along a single, inspectable path. Each day adds new options: generate and execute code on the fly, delegate subtasks to MCP-backed tools, contract external specialists via A2A, chain services that themselves invoke other services. The agent’s action space is no longer a tree. It is a graph that keeps expanding while the agent is already moving through it. What used to be a prompt-and-response system now behaves like a distributed system assembled at runtime. |
![]() |
Beyond MES: How General AI Agents Deliver Custom Manufacturing Solutions On Demand
Manufacturing professionals often find themselves caught between two unsatisfying options: expensive, rigid MES implementations or cobbling together spreadsheets and manual processes. But there's a third path emerging - one that combines the sophistication of custom software with the accessibility of a conversation. |
We use Anthropic Sonnet 4.5 via console account (default). To use OpenAI models (GPT-5-Codex, GPT-5-mini), configure the LiteLLM proxy.
You need to create an .env file inside the backend directory:
# Anthropic API Key (used for direct Claude API calls when aiModel=claude)
ANTHROPIC_API_KEY=sk-ant-api03-...AA
# Local data directory root for all projects
WORKSPACE_ROOT=C:/Data/GitHub/claude-multitenant/workspace
# Only used for deep research module (optional), enter any string but don't remove(!)
OPENAI_API_KEY=34343434343434
# Memory Management Configuration
MEMORY_MANAGEMENT_URL=http://localhost:6060/api/memories
MEMORY_DECAY_DAYS=6
# Budget Control Configuration
COSTS_CURRENCY_UNIT=EUR
COSTS_PER_MIO_INPUT_TOKENS=3.0
COSTS_PER_MIO_OUTPUT_TOKENS=15.0
# Checkpoint Provider Configuration
CHECKPOINT_PROVIDER=gitea
GITEA_URL=http://localhost:3000
GITEA_USERNAME=your.user@gitea.local
GITEA_PASSWORD=****
GITEA_REPO=workspace-checkpoints
The checkpoint feature requires Gitea to be installed and running on localhost:3000. Checkpoints create versioned backups of your project workspace and store them in a Gitea repository.
Prerequisites:
- Gitea server running on port 3000
- Valid Gitea user account (configured in
.env)
Configuration:
The checkpoint system uses environment variables in .env:
CHECKPOINT_PROVIDER- Provider type:gitea(default) orgit(fallback)GITEA_URL- Gitea server URL (default:http://localhost:3000)GITEA_USERNAME- Gitea user email for authenticationGITEA_PASSWORD- Gitea user passwordGITEA_REPO- Repository name for checkpoints (default:workspace-checkpoints)
Provider Options:
-
Gitea Provider (default, recommended)
- Stores checkpoints in a Gitea repository at
localhost:3000 - Creates one repository with project folders (e.g.,
workspace-checkpoints/project1/,workspace-checkpoints/project2/) - Uses Gitea REST API for all operations
- Works on Windows/Linux without Docker
- Handles large files (>1MB) via raw download endpoint
- Stores checkpoints in a Gitea repository at
-
Git Provider (fallback)
- Stores checkpoints in a local git repository inside the Docker container
- Located at
/workspace/.checkpointsin the container - Uses git commands via Docker exec (development) or direct shell (production)
- Requires
claude-codeDocker container to be running - Legacy option maintained for backwards compatibility
How it works:
- Each checkpoint is a tarball (
.tar.gz) of the project directory - Checkpoints are tracked in
.etienne/checkpoints.jsonmanifest file - The manifest stores checkpoint metadata: timestamp, commit message, and git commit hash
- Restore operations extract the tarball and overwrite project files (except
checkpoints.json)
To switch to the Git provider, set CHECKPOINT_PROVIDER=git in your .env file.
The frontend requires authentication via a lightweight OAuth/JWT server running on port 5950.
Starting the OAuth server:
cd oauth-server
npm install
npm run devDefault credentials:
| Username | Password | Role |
|---|---|---|
| admin | admin123 | admin |
| user | user123 | user |
| guest | guest123 | guest |
User management:
Users are configured in oauth-server/config/users.json. To add or change a password, generate a bcrypt hash:
cd oauth-server
npm run hash-password YourNewPassword123Copy the output hash into the passwordHash field in users.json.
Token behavior:
- Access tokens expire after 15 minutes (configurable in
users.json) - Refresh tokens expire after 7 days
- "Remember me" stores tokens in localStorage; otherwise sessionStorage
Start the OAuth server on :5950
cd oauth-server
npm i
npm run dev
Start the backend on :6060
cd backend
npm i
npm run dev
Start the frontend on :5000
cd frontend
npm i
npm run dev
Then open your browser with http://localhost:5000
The frontend requires authentication before use. You must start the OAuth server manually before accessing the application.
Quick Start:
- Start the OAuth server (see "Starting up the services" above)
- Open http://localhost:5000 in your browser
- Login with username
userand passworduser123
Managing Users:
Users and credentials are configured in oauth-server/config/users.json. Each user has a username, bcrypt-hashed password, role, and display name.
Available Roles:
guest- Read-only accessuser- Full chat and project accessadmin- All permissions including user management
Creating Password Hashes:
To add a new user or change a password, generate a bcrypt hash using the provided script:
cd oauth-server
npm run hash-password MyNewPassword123This outputs a hash like $2b$10$... which you copy into the passwordHash field in users.json.
Example users.json entry:
{
"id": "u4",
"username": "newuser",
"passwordHash": "$2b$10$your-generated-hash-here",
"role": "user",
"displayName": "New User",
"enabled": true
}The Knowledge Base feature provides a hybrid semantic search system combining RDF knowledge graphs and vector stores for intelligent information retrieval. It enables storing, querying, and visualizing structured knowledge extracted from documents.
The system consists of three microservices:
-
Backend API (
/backend- NestJS on port 6060)- Coordinates between vector store and RDF store services
- Handles entity extraction using OpenAI GPT-4.1-mini
- Generates embeddings using OpenAI text-embedding-3-small
- Provides unified REST API for knowledge graph operations
-
Vector Store Service (
/vector-store- Python FastAPI on port 7100)- Multi-tenant ChromaDB server with project isolation
- Each project gets dedicated ChromaDB instance:
workspace/<project>/knowledge-graph/chroma.sqlite3 - Uses cosine similarity for semantic search (configured via
hnsw:space: cosine) - Persistent storage with HNSW indexing for fast retrieval
- RESTful API:
/api/v1/{project}/collections/{collection}/...
-
RDF Store Service (
/rdf-store- Node.js Quadstore on port 7000)- Multi-tenant RDF triple store with LevelDB backend
- Stores entities and relationships as RDF triples
- Supports SPARQL 1.1 queries for graph traversal
- Persistent storage:
workspace/<project>/knowledge-graph/(LevelDB files) - RESTful API with SPARQL endpoint
Documents uploaded to the Knowledge Base are automatically processed:
- Upload → Backend API receives markdown content
- Embedding Generation → OpenAI creates vector embeddings (text-embedding-3-small)
- Vector Storage → Document + embedding stored in ChromaDB via HTTP API
- Entity Extraction (optional, if "Use Graph Layer" enabled):
- OpenAI GPT-4.1-mini extracts entities using custom or default schema
- Entities parsed from structured JSON response
- RDF Storage → Entities and relationships stored as triples via Quadstore HTTP API
- Deduplication → Entities deduplicated by type and ID before RDF insertion
Each project can customize entity extraction behavior:
Entity Schema (.etienne-entity-schema.json):
- Define entity types (e.g., Company, Employee, Technology, Product)
- Specify JSON schema for structured extraction
- Configure relationships between entity types
- Stored as RDF ontology definitions
Extraction Prompt (.etienne-extraction-prompt.md):
- Custom instructions for the AI extraction model
- Define extraction rules and guidelines
- Specify output format and entity criteria
- Fallback to default if not configured
Configuration files location:
workspace/<project>/knowledge-graph/
├── .etienne-entity-schema.json # RDF ontology schema
└── .etienne-extraction-prompt.md # Entity extraction prompt
The Knowledge Base supports multiple query interfaces:
-
Similarity Search (Primary Interface)
- Semantic search using ChromaDB cosine similarity
- OpenAI embeddings for query vectorization
- Configurable threshold filter (default: 20% minimum similarity)
- Results sorted by similarity descending
- Displays: Document ID, content preview, similarity score, graph layer status
-
Natural Language Search (Graph Layer)
- Translates natural language to SPARQL automatically
- Uses GPT-4 for query translation
- Example: "Who works at which company?"
-
SPARQL Queries (Graph Layer)
- Direct SPARQL query execution against Quadstore
- Full SPARQL 1.1 specification support
- Graph pattern matching and filtering
-
Hybrid Search
- Combines vector similarity (70% weight) and graph queries (30% weight)
- Provides comprehensive results from both systems
- Merged and ranked by relevance score
The frontend provides an interactive graph visualization:
- Graph Viewer: Renders entities and relationships as interactive nodes/edges
- Node Click: Displays source documents containing clicked entities
- Statistics Dashboard: Shows entity counts, document counts, and RDF triple counts
- Monaco Editor: Inline SPARQL query editor with syntax highlighting
Services Required:
-
ChromaDB Vector Store (port 7100):
cd vector-store pip install -r requirements.txt python multi-tenant-chromadb.py- Uses ChromaDB 1.3.4+ with HNSW indexing
- Persistent storage:
workspace/<project>/knowledge-graph/chroma.sqlite3 - Automatically configures cosine similarity for all collections
-
Quadstore RDF Store (port 7000):
cd rdf-store npm install node server.js- Uses Quadstore with LevelDB backend
- Persistent storage:
workspace/<project>/knowledge-graph/(LevelDB) - SPARQL 1.1 query support
External API Dependencies:
- OpenAI API: Required for embeddings (
text-embedding-3-small) and entity extraction (gpt-4.1-mini) - Configured via
OPENAI_API_KEYin backend.env
Data Location:
workspace/<project>/knowledge-graph/
├── chroma.sqlite3 # ChromaDB vector embeddings
├── CURRENT # LevelDB descriptor files
├── LOCK # LevelDB lock
├── LOG # LevelDB transaction log
├── MANIFEST-* # LevelDB manifest
└── *.ldb, *.log # LevelDB SSTable files (RDF triples)
- Document Knowledge Extraction: Upload research documents, extract entities automatically
- Relationship Mapping: Discover connections between people, companies, and technologies
- Semantic Search: Find documents by meaning, not just keywords
- Graph Queries: Answer complex questions requiring multi-hop reasoning
- Custom Ontologies: Define domain-specific entity types and relationships
The Context Management system provides fine-grained control over which data sources Claude Code can access during task execution. By applying tags to files, vector documents, and knowledge graph entities, you can create named contexts that scope the agent's view to only relevant information.
- Reduce Token Costs: Limit Claude's filesystem and knowledge base access to only relevant files/data
- Improve Response Quality: Focus the agent on specific domains or project areas
- Multi-tenant Isolation: Separate customer data, departments, or project phases
- Privacy & Security: Exclude sensitive files or documents from specific sessions
a) Why to use?
When working on large projects with hundreds of files, filesystem contexts allow you to tag files by domain (e.g., frontend, backend, docs) and create contexts that include/exclude specific tags. This prevents Claude from reading irrelevant files and reduces token consumption.
b) How to apply in the UI
- Navigate to the Filesystem panel
- Right-click any file or folder to open the context menu
- Select "Manage Tags" to add tags like
api,frontend,tests, etc. - Open Project Menu → Context/Tagging (or click the tag icon in the app bar)
- Create a new context with:
- Include files with tags: Select tags like
frontend,ui - Exclude files with tags: Select tags like
tests,legacy
- Include files with tags: Select tags like
- Switch to the created context using the Context Switcher in the app bar
c) How it affects the agent's data access internally
When a context is active for a session, the backend filters the filesystem tree returned to Claude Code based on tag rules:
- Files with matching include tags are shown
- Files with exclude tags are hidden, even if they match include tags
- The agent can only read, edit, or reference files within the scoped view
- API endpoint:
GET /api/workspace/:project/contexts/:contextId/scopereturns filtered file paths
a) Why to use?
Vector stores contain embedded documents for semantic search. By tagging documents (e.g., product-docs, customer-feedback, internal-wiki), you can create contexts that limit which document collections Claude can search through, improving search relevance and reducing API costs.
b) How to apply in the UI
- When uploading documents to the Knowledge Graph Browser, add tags during upload
- Alternatively, tag existing documents via the document management interface
- Open Project Menu → Context/Tagging
- Create a new context and configure:
- Vector document tags: Select tags like
product-docs,api-specs
- Vector document tags: Select tags like
- Activate the context using the Context Switcher
c) How it affects the agent's data access internally
When a context with vector tag filters is active:
- Semantic search queries are restricted to documents matching the specified tags
- The vector store filters results by metadata tags before computing similarity scores
- Only matching documents contribute to the agent's knowledge retrieval
- ChromaDB metadata filter:
where: { "tags": { "$in": ["selected-tag"] } }
a) Why to use?
Knowledge graphs store structured entities (People, Companies, Products) and relationships extracted from documents. Contexts allow you to scope queries to specific entity types or tagged subgraphs, enabling domain-specific reasoning while excluding unrelated data.
b) How to apply in the UI
- Ensure entities are tagged during ingestion (e.g.,
project-alpha,Q4-2024) - Open Project Menu → Context/Tagging
- Create a new context and configure:
- Entity tags: Select tags like
project-alpha,customer-facing - Entity types: Select types like
Person,Company,Product
- Entity tags: Select tags like
- Activate the context via the Context Switcher
c) How it affects the agent's data access internally
When a knowledge graph context is active:
- SPARQL queries are automatically filtered by entity type and tag predicates
- Only entities matching the context's type/tag filters are returned
- Relationship traversal is limited to entities within scope
- Example SPARQL filter:
?entity rdf:type <Company> . ?entity etienne:hasTag "project-alpha" - Natural language to SPARQL translation includes context filters automatically
Each chat session maintains its own active context independently. This enables:
- Multi-user scenarios: Different users working on the same project with different data scopes
- Task isolation: Switch contexts mid-conversation without affecting other sessions
- Context comparison: Run the same query in different contexts to compare results
The active context is stored in session metadata (GET /api/sessions/:project/:sessionId/context) and applied automatically to all data access operations during that session.
The backend supports OpenTelemetry-based observability for monitoring LLM conversations and tool usage. When enabled, traces are sent to an OTLP-compatible collector like Arize Phoenix.
Set these environment variables in backend/.env:
| Variable | Description | Default |
|---|---|---|
OTEL_ENABLED |
Set to "true" to enable telemetry |
(disabled) |
PHOENIX_COLLECTOR_ENDPOINT |
Base URL of the OTLP collector | http://localhost:6006 |
OTEL_SERVICE_NAME |
Service name in traces | etienne |
docker run -d --name phoenix -p 6006:6006 -p 4317:4317 arizephoenix/phoenix:latestThen enable telemetry:
# Add to backend/.env
OTEL_ENABLED=true
PHOENIX_COLLECTOR_ENDPOINT=http://localhost:6006The implementation follows OpenInference Semantic Conventions for LLM-specific attributes.
Conversation Spans (Agent):
llm.model_name,llm.provider,llm.systemllm.token_count.prompt,llm.token_count.completion,llm.token_count.totalinput.value,output.value(prompt and response)session.id,project.name,user.idagent.tools_used,agent.tool_call_count
Tool Spans (nested under conversation):
tool.name,tool.parameters,tool.outputtool.status(success/error),tool.duration_mstool.error_message(if applicable)
- Open Phoenix UI at
http://localhost:6006 - Navigate to the Traces view
- Filter by
project.nameorsession.idto find specific conversations - Click on a trace to see the conversation span with nested tool spans
This project follows a specification-driven development approach. All features are documented as Product Requirements Documents (PRDs) in the /requirements-docs folder. Below is a comprehensive overview of all features, categorized by their role in the system.
These features directly control or modify how Claude Code operates internally:
-
Subagents (/requirements-docs/prd-subagents.md) Enables creation and management of specialized subagents that Claude can delegate tasks to autonomously. Each subagent is defined with a name, description, custom system prompt, restricted tool access, and model selection. Subagents allow for specialized workflows like code review, testing, and debugging to be triggered automatically based on context.
-
Permissions (/requirements-docs/prd-permissions.md) Provides granular control over which tools Claude Code can use through a configurable permissions system. Permissions are stored per-project in
.claude/permissions.jsonand define allowed tools with glob patterns (e.g.,Write(./**/*.py),Bash(python3:*)). This enables sandboxing and safety constraints for different project contexts. -
MCP Servers (/requirements-docs/prd-mcp-servers.md) Enables integration of Model Context Protocol (MCP) servers to extend Claude's capabilities with external tools and data sources. Each project can configure MCP servers in
.mcp.jsonwith settings for transport type (SSE/HTTP/STDOUT), authentication, and endpoints. MCP servers provide custom tools that become available to Claude during task execution. -
Dynamic Python MCP Tools (Hot-Reloadable) Enables users and agents to create Python-based MCP tools directly in project directories that are automatically discovered and served by the existing MCP server without restart. Tools placed in
.etienne/tools/*.pyare detected via file watcher, parsed for metadata, and exposed aspy_<toolname>tools. Supports automatic pip dependency installation fromrequirements.txt. See Dynamic Python MCP Tools section below for details. -
Interceptors (/requirements-docs/prd-interceptors.md) Implements real-time tracking and tracing of Claude Code's behavior through hooks and events. All tool calls (PreToolUse/PostToolUse) and system events are captured, stored in-memory, and streamed to the frontend via SSE. This provides complete visibility into the agentic cycle for debugging, monitoring, and understanding Claude's decision-making process.
-
Cancel and Limit Agentic Cycle (/requirements-docs/prd-cancel-and-limit-agentic-cycle.md) Provides user control over long-running agentic loops through configurable max-turns limits and a process abortion mechanism. Users can set a maximum number of agentic cycles (default: 5, 0=unlimited) and abort running processes via a stop button. This prevents runaway costs and allows quick iteration during development.
-
Strategy (/requirements-docs/prd-strategy.md) Allows per-project customization of Claude's system prompt through a
.claude/CLAUDE.mdfile. Users can edit the strategy file directly in a Monaco editor to define the agent's role, behavior, domain knowledge, and task-specific instructions. This enables tailoring Claude's behavior for different project types and workflows. -
Input Guardrails (/requirements-docs/prd-input-guardrails.md) Implements a plugin-based system to detect and redact sensitive information from user input before it reaches the AI model. Built-in plugins detect credit cards (with Luhn validation), IP addresses (IPv4/IPv6), emails, URLs, and IBANs. Each project can configure which guardrails are active via
.etienne/input-guardrails.json. -
Output Guardrails (/requirements-docs/prd-output-guardrails.md) Provides LLM-based post-processing to inspect and redact policy violations from Claude Code's responses. Uses a customizable prompt with GPT-4o-mini to detect violations, replace them with placeholders, and emit violation events to the frontend. When enabled, response streaming is disabled to allow buffering and content modification before delivery.
These features enhance or support the agentic cycle but don't directly control it:
-
Session Management (/requirements-docs/prd-session-management.md) Implements multi-session conversation management with automatic summarization and persistence. Sessions are stored in separate JSONL files (
.etienne/chat.history-<sessionId>.jsonl) with a session index inchat.sessions.json. Users can start new sessions, resume previous conversations, and view AI-generated summaries of past sessions.Named Session Routing: Automated callers (Scheduler, Condition Monitor, Workflow Entry Actions) route their output to fixed named sessions instead of appending to whichever user session happens to be the most recent. This prevents automated output from polluting interactive conversations. Each named session (
Scheduled Tasks,Condition Monitoring,Workflow Actions) is created on first use with a deterministic ID and pinned to the top of the session drawer with a distinct icon and colored border. Remote Sessions (Telegram/Teams) retain the original most-recent-session behavior since they represent interactive conversations from external providers. -
Scheduling Subsystem (/requirements-docs/prd-scheduling-subsystem.md) Provides cron-based task scheduling using NestJS Schedule to automatically invoke Claude Code with predefined prompts. Task definitions include name, prompt, cron expression, and timezone. Execution history tracks timestamp, response, errors, duration, and token usage. Supports daily, weekly, or custom scheduling patterns.
-
Checkpoints (/requirements-docs/prd-checkpoints.md) Implements Git-based backup and restore functionality for project workspaces. Creates versioned snapshots of project files with descriptive commit messages, stores them in
/workspace/.checkpoints, and allows rolling back to any previous state. Operates via Docker exec in development and direct Git commands in production. -
Budget Control (/requirements-docs/prd-budget-control.md) Tracks and visualizes AI inference costs on a per-project basis. Records input/output tokens and calculates costs based on configurable rates in
.env. Displays real-time budget indicators with percentage-based icons (0-100%) and alerts when limits are exceeded. Stores detailed cost history in.etienne/costs.jsonsorted from newest to oldest. -
Long-term Memory (/requirements-docs/prd-long-term-memory.md) Implements agentic memory extraction and retrieval using GPT-4o-mini for fact extraction from conversations. Stores structured memories in
.etienne/memories.jsonwith automatic decay based on configurable time windows. Supports memory search, update, and deletion. Extracted facts include personal information, preferences, goals, habits, skills, and context. -
Chat Persistence (/requirements-docs/prd-chat-persistence.md) Provides persistent storage of chat history and initial assistant greetings. Chat messages are stored in
chat.history.jsonwith timestamps, role indicators (user/agent), message content, and cost data. Assistant greetings are configured per-project inassistant.jsonand displayed as the first message when loading a project.
UI/UX features, administrative tools, and system utilities:
-
System Diagnosis (/requirements-docs/prd-system-diagnosis.md) Implements health checks for the backend and Claude Code Docker container. Frontend polls
/api/claude/healthevery 10 seconds to detect issues like missing Docker, container not running, or unsupported Claude versions. Displays persistent markdown-formatted toast notifications with troubleshooting instructions when errors are detected. -
Help System (/requirements-docs/prd-help-system.md) Provides contextual background information through dismissible toast components. Each component displays markdown-formatted help text with optional icons, stored in
/public/background-info/data.json. Help toasts appear in key UI sections (strategy, permissions, integrations, interceptors, filesystem) and can be toggled on/off in settings. -
Filesystem (/requirements-docs/prd-filesystem.md) Displays project file structure in a hierarchical tree view using MUI SimpleTreeView. Shows folders with expand/collapse icons and files with document icons. Provides a refresh button to reload the tree structure. Backend API returns sorted directory listings with all files and folders in the project workspace.
-
Structured Chat Responses (/requirements-docs/prd-structured-chat-responses.md) Migrates from plain text streaming to structured event-based response handling. Parses Claude Code stdout into specialized components for user messages, tool calls (with running/complete states), permission requests (with approve/deny buttons), errors, and subagent activity. Maintains the existing interceptors system for hooks and events.
-
Live HTML Preview (/requirements-docs/prd-live-html-preview.md) Provides real-time preview of HTML files in an iframe with automatic refresh when files are modified. Listens for PostHook events via the interceptors system and reloads the preview when Claude makes changes to HTML files. Uses sandboxed iframes with controlled permissions for security.
-
Refactoring File Explorer (/requirements-docs/prd-refactoring-fileexplorer.md) Enhances the filesystem component with drag-and-drop file uploads, inline renaming, file/folder deletion, and drag-to-move functionality. Implements Material Design styled tree with folder open/closed states and document icons. Backend API supports DELETE, POST, and PUT operations for file management in
/api/workspace/:project/files/. -
Frontend State (/requirements-docs/prd-frontend-state.md) Manages frontend state persistence using localStorage to remember the currently loaded project. Controls UI element visibility and enabled/disabled states based on whether a project is loaded. Validates that stored projects exist in the workspace on startup and gracefully handles missing projects.
The frontend includes specialized preview components for various file types through the FilePreviewHandler service. When files are selected in the filesystem browser, they are automatically opened in the appropriate viewer component within the Artifacts pane.
| File Extension | Viewer Component | Description |
|---|---|---|
.html, .htm |
LiveHTMLPreview | Renders HTML files in a sandboxed iframe with automatic refresh on file changes |
.json |
JSONViewer | Displays JSON data with syntax highlighting and formatting |
.md |
MarkdownViewer | Renders Markdown files with full formatting support |
.mermaid |
MermaidViewer | Renders Mermaid diagrams (flowcharts, sequence diagrams, etc.) |
.research |
ResearchDocument | Specialized viewer for research documents with structured content |
.jpg, .jpeg, .png, .gif |
ImageViewer | Displays images at original size with extracted header metadata (dimensions, bit depth, color type, compression) |
.xls, .xlsx |
ExcelViewer | Interactive Excel spreadsheet viewer using SheetJS and wolf-table with multi-sheet support, scrollable/resizable cells, Roboto font, and read-only mode |
- FilePreviewHandler detects file extensions and publishes
FILE_PREVIEW_REQUESTevents to the event bus - ArtifactsPane listens for these events, closes the filesystem drawer, and switches to the "Artifacts" tab
- FilesPanel renders the appropriate viewer component based on the file extension
- For unsupported file types, content is displayed as plain text with monospace formatting
The preview system is integrated with the Interceptors feature to automatically refresh previews when files are modified by Claude Code.
Etienne supports external messaging platform integration, allowing users to interact with projects directly from messaging apps like Telegram. The system uses a secure pairing mechanism where all users are blocked by default until explicitly approved by an admin.
sequenceDiagram
actor TelegramUser as Telegram User
participant Provider as Telegram Provider<br/>(:6350)
participant Backend as Backend<br/>(:6060)
participant Admin as Admin<br/>(Frontend)
rect rgb(240, 240, 255)
Note over TelegramUser,Admin: Pairing Flow (first time only)
TelegramUser->>Provider: /start
Provider->>Backend: POST /remote-sessions/pairing/request
Backend-->>Admin: Pairing request appears in UI
Admin->>Backend: Approve pairing
Backend-->>Provider: Session created
Provider-->>TelegramUser: ✓ Paired — select a project
end
TelegramUser->>Provider: Send message
Provider->>Backend: Check session mapping
Backend-->>Provider: Session valid
Provider->>Backend: Forward prompt to Etienne
Backend-->>Provider: Etienne response (streamed)
Provider-->>TelegramUser: Reply to user
Components:
- Telegram Provider (
/telegram) - Grammy-based bot using long polling, handles messages and media uploads - Remote Sessions Module (
/backend/src/remote-sessions) - Manages session mappings and pairing requests - Frontend Pairing Modal - Admin approval interface for new user pairing requests
Create a .env file in the /telegram directory:
# Required: Telegram Bot Token from @BotFather
TELEGRAM_BOT_TOKEN=your-bot-token-here
# Optional: Backend URL (default: http://localhost:6060)
BACKEND_URL=http://localhost:6060To create a Telegram bot:
- Open Telegram and search for @BotFather
- Send
/newbotand follow the prompts - Copy the bot token provided by BotFather
Starting the Provider:
cd telegram
npm install
npm run dev # Development modePairing Flow:
- User sends
/startto the Telegram bot - A pairing request appears in the Etienne web UI
- Admin clicks Approve or Deny in the modal dialog
- Once approved, user can select a project and start chatting
Available Commands:
| Command | Description |
|---|---|
/start |
Begin pairing or show current status |
/status |
Show current session status |
/projects |
List available projects |
/disconnect |
Disconnect from Etienne |
/help |
Show available commands |
Project Selection:
project 'project-name'
Sending Files:
Users can send photos, documents, videos, and audio files which are automatically uploaded to the project's .attachments folder.
More information: See telegram/README.md for complete documentation including troubleshooting and development guides.
MCP tools can serve interactive UIs directly inside the chat timeline. When a tool carries a _meta.ui.resourceUri, its result is rendered as a full MCP App (sandboxed iframe) instead of plain JSON, giving the user buttons, forms and live data right where the conversation happens.
One use case it the configuration of Etienne which can be optionally managed using the etienne configuration MCP tool:
The integration uses @mcp-ui/client on the host side (React frontend) and @modelcontextprotocol/ext-apps inside the iframe (guest app).
sequenceDiagram
actor User
participant Frontend as StreamingTimeline<br/>(React)
participant Renderer as McpAppRenderer<br/>(AppRenderer)
participant Proxy as Sandbox Proxy<br/>(iframe)
participant GuestApp as Guest App<br/>(MCP App React)
participant Backend as Backend MCP Server<br/>(:6060)
User->>Frontend: Send prompt
Frontend->>Backend: Claude calls MCP tool (e.g. list_services)
Backend-->>Frontend: JSON result via SSE<br/>with _meta.ui.resourceUri
Note over Frontend: useMcpAppMeta detects<br/>resourceUri → render McpAppRenderer
Renderer->>Backend: Connect MCP client via<br/>StreamableHTTPClientTransport
Backend-->>Renderer: Session established
Renderer->>Backend: resources/read (ui://…/dashboard.html)
Backend-->>Renderer: HTML resource (597 KB single-file)
Renderer->>Proxy: Create iframe at /sandbox-proxy
Proxy-->>Renderer: sandbox-proxy-ready
Renderer->>Proxy: sandbox-resource-ready { html }
Proxy->>GuestApp: Load HTML in nested srcdoc iframe
GuestApp-->>Proxy: initialized
Proxy-->>Renderer: initialized
Renderer->>Proxy: tool-input + tool-result
Proxy->>GuestApp: tool-input + tool-result
loop Interactive use (poll, start, stop, config)
GuestApp->>Proxy: callServerTool (e.g. list_services)
Proxy->>Renderer: callServerTool
Renderer->>Backend: tools/call
Backend-->>Renderer: Tool result JSON
Renderer->>Proxy: Tool result
Proxy->>GuestApp: Tool result
end
| Layer | File | Purpose |
|---|---|---|
| Backend | etienne-configuration-tools.ts | Tool definitions with _meta.ui.resourceUri, resource HTML loader |
| Backend | mcp-server-factory.service.ts | Registers resource handlers (resources/list, resources/read), exposes getToolAppMeta() |
| Backend | mcp-server.controller.ts | GET /mcp/tool-app-meta endpoint for frontend discovery |
| Backend | types.ts | McpResource interface, ToolGroupConfig.resources |
| Frontend | McpAppRenderer.jsx | Wraps AppRenderer, connects MCP client to backend |
| Frontend | useMcpAppMeta.js | Fetches tool-app metadata, maps both raw and mcp__-prefixed names |
| Frontend | StreamingTimeline.jsx | Detects MCP App tools, renders McpAppRenderer inline |
| MCP App | mcp-app-etienne-config/server.ts | Standalone MCP App server (development/testing) |
| MCP App | mcp-app-etienne-config/src/mcp-app.tsx | React dashboard UI (Services + Configuration tabs) |
- Create a React app under
mcp-app-<name>/usingvite-plugin-singlefileto produce a single HTML file indist/ - In your tool definition, add
_meta: { ui: { resourceUri: 'ui://<name>/dashboard.html' } }to the entry tool - Register a
McpResourcein the tool group's config insidemcp-server-factory.service.tswith aloadContentfunction pointing at the built HTML - Add the group to
mcp-server-registry.json - The frontend picks it up automatically via
/mcp/tool-app-meta
AppRenderer from @mcp-ui/client requires a sandbox proxy — a small HTML page that bridges postMessage communication between the host and a nested iframe containing the MCP App HTML. This provides iframe isolation so the guest app cannot access the host page's DOM, cookies, or storage.
How it works:
Host (AppRenderer on :5000)
│
└─ <iframe src="/sandbox-proxy?contentType=rawhtml"> ← proxy iframe
│
└─ <iframe srcdoc="..."> ← MCP App HTML
│
└─ postMessage ↔ proxy ↔ host (JSON-RPC)
AppRenderercreates an iframe pointing at the proxy URL- The proxy signals readiness via
{ method: "ui/notifications/sandbox-proxy-ready" } - The host sends the MCP App HTML via
{ method: "ui/notifications/sandbox-resource-ready", params: { html } } - The proxy loads the HTML into a nested
srcdociframe withsandbox="allow-scripts" - All subsequent JSON-RPC messages (tool calls, size changes, etc.) are forwarded bidirectionally
Configuration:
The proxy is served by a Vite middleware plugin at /sandbox-proxy on the same origin (port 5000). No additional ports are required, making it Docker-compatible.
| File | Purpose |
|---|---|
| sandbox_proxy.html | The proxy HTML — receives HTML via postMessage, creates nested iframe, forwards messages |
| vite.config.js | mcpSandboxProxyPlugin serves sandbox_proxy.html at /sandbox-proxy via Vite middleware |
| McpAppRenderer.jsx | Passes sandbox={{ url: new URL('/sandbox-proxy', origin) }} to AppRenderer |
Note: The @mcp-ui/client library checks whether the proxy origin matches the host origin. For AppRenderer (used for full MCP Apps with bidirectional tool calls), same-origin proxies work correctly. The origin check only blocks same-origin in HTMLResourceRenderer (a simpler component not used here).
Etienne tracks AI inference costs per project and enforces a global budget limit across all projects.
The budget pane can be activated from the app bar.
- Always-on tracking: Token usage is recorded for every Claude request regardless of whether the budget limit is enabled. Each cost entry includes a timestamp, session ID, input/output tokens, per-request cost, and accumulated cost.
- Session-based counting: A "task" in the budget dashboard corresponds to a distinct chat session (identified by
sessionId), not an individual API call. The dashboard shows the number of unique sessions, not raw request counts. - Global budget limit: The configured limit applies to the sum of costs across all projects in the workspace, not per-project. This prevents circumventing the budget by splitting work across projects.
- Pre-flight enforcement: Before processing any chat request (direct, streamed, or unattended), the backend checks whether the global budget has been exceeded and rejects the request if so.
- Default settings: Budget monitoring is enabled by default with a limit of 200 €.
Costs are computed from token counts using configurable rates:
cost = (inputTokens / 1,000,000) × COSTS_PER_MIO_INPUT_TOKENS
+ (outputTokens / 1,000,000) × COSTS_PER_MIO_OUTPUT_TOKENS
| Variable | Default | Description |
|---|---|---|
COSTS_CURRENCY_UNIT |
EUR |
Currency code shown in the UI (EUR, USD, GBP, JPY) |
COSTS_PER_MIO_INPUT_TOKENS |
3.0 |
Cost per million input tokens |
COSTS_PER_MIO_OUTPUT_TOKENS |
15.0 |
Cost per million output tokens |
Each project stores its data under the .etienne/ directory:
| File | Purpose |
|---|---|
.etienne/costs.json |
Array of cost entries (newest first), one per API call |
.etienne/budget-monitoring.settings.json |
{ enabled, limit } — budget on/off and limit value |
The budget indicator in the header bar shows a percentage icon (0–100 %) based on global spend vs. limit. Clicking it opens a drawer with:
- Stacked progress bar — blue portion represents all other projects, red represents the current project
- Tiles — tokens used, tokens remaining (estimated), sessions completed, average cost per session
- Recent Activity — collapsible table of the last 10 cost entries (collapsed by default)
- Budget Settings — dialog to change the limit; includes a "Reset token counters" checkbox (enabled by default) that clears cost history for all projects when saved
The frontend subscribes to an SSE stream (/api/budget-monitoring/:project/stream) that pushes budget-update events whenever a new cost entry is recorded. On each event the UI also re-fetches global totals to keep the stacked bar accurate.
Brought to you by e-ntegration GmbH, Nürnberg, Germany.
Happy building!




























































