Skip to main content

Open-source AI agent for Microsoft 365.

Project description

 ███████╗██████╗ ███████╗ █████╗ ███╗   ██╗
 ██╔════╝██╔══██╗██╔════╝██╔══██╗████╗  ██║
 █████╗  ██████╔╝███████╗███████║██╔██╗ ██║
 ██╔══╝  ██╔══██╗╚════██║██╔══██║██║╚██╗██║
 ███████╗██║  ██║███████║██║  ██║██║ ╚████║
 ╚══════╝╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚═╝  ╚═══╝

Your office. Your rules. Your AI. ...and you, amplified.

Open-source AI agent for Microsoft 365. Apache 2.0. Runs on your laptop against your own tenant. No data leaves unless you tell it to.


Why ersan

If you use Microsoft 365 and want an AI agent that:

  • doesn't ship your inbox to a third-party SaaS,
  • gates every action through a policy you can read,
  • redacts PII and credentials from outbound text,
  • ships a working CLI in seconds via pip install,
  • is bilingual out of the box (English + Turkish); community translations welcome — see docs/i18n.md,

then ersan is for you.

Architecture

ersan is the gate (owns the user relationship), not infrastructure (consumed by other agents). Capabilities load as skills, packaged into plugins.

Three pillars:

  • Core: pydantic-ai Agent runtime, CLI, REPL
  • Policy: trust tiers (ask_first, do_and_tell, do_it) gating every tool call
  • Shield: PII / credential redaction on outbound text + ReDoS-safe regex compilation, audit-log SHA-256 hash chain, and per-run policy isolation (defense-in-depth landed in v0.5.0; see SECURITY.md)

In the current runtime, ersan's core is pydantic_ai.Agent. Tool selection is LLM-driven from natural-language prompts, ersan.policy enforces tier-based gating via PolicyCapability.wrap_tool_execute(), and ersan.shield enforces pattern-based blocking plus redaction via ShieldHook registered on the tool:pre event of ersan.hooks.HookRegistry, fired by HookBridgeCapability.

The ersan runtime ships no bundled M365 toolset yet — Microsoft Graph OAuth via MSAL and the Outlook inbox skills are scheduled for a future release (US-007). Today the CLI exposes the bare Agent runtime: bring your own toolset (see docs/skills.md) or wait for the bundled Inbox MVP.

Privacy

  • No telemetry. Zero phone-home.
  • No third-party LLM calls unless your config calls them. Structurally enforced — local-provider client construction is covered by tests/integration/test_local_provider_no_network.py, which proves the provider factories make zero outbound requests during construction.
  • LLM credentials stay local. API keys live in ERSAN_LLM_API_KEY (your env), never written to disk by ersan, never logged, redacted as *** in ersan config output and JSON repr (via pydantic.SecretStr). M365 OAuth tokens are NOT yet stored — the MSAL device-code flow lands with US-007.
  • Audit-log to your own sink (~/.ersan/audit.log). Every entry carries a SHA-256 prev_hash (v0.5.0) so tampering is detectable via ersan.policy.audit.verify_audit_chain.

Platform support

ersan is platform-agnostic by construction (per Constitution §Cross-platform invariants). Every PR runs against:

  • Per PR (6 jobs): ubuntu-latest × Python 3.10 / 3.11 / 3.12 / 3.13; windows-latest × Python 3.13; macos-latest × Python 3.13.
  • Weekly cron (12 jobs): full cartesian — every supported OS × every supported Python version.
  • On every release tag (6 jobs): smoke-install matrix — {ubuntu, windows, macos} × {Python 3.10, 3.13} runs pip install against the freshly built wheel before it reaches PyPI via Trusted Publishing with Sigstore PEP 740 attestations.

A wheel does not reach PyPI until the smoke-install matrix passes on all three operating systems.

Roadmap

Version Status Shipped
v0.1.x ✅ released Architecture-complete: foundations + eval harness + skill loader
v0.2.x ✅ released Model Provider Abstraction — ersan.providers, local-first Ollama config, Anthropic config, privacy-invariant provider tests
v0.3.0 ✅ released Constitutional pillars — bundled slim port of ersan.policy + ersan.shield, wired into the loader with the default retail ask_first policy and ~/.ersan/audit.log audit path
v0.4.0 ✅ released Agent runtime adoption — pydantic_ai.Agent, PolicyCapability, HookBridgeCapability, slim REPL + one-shot CLI (US-006)
v0.5.0 ✅ released Env-first config (pydantic-settings + Catwalk-style provider registry, US-010) + defense-in-depth security primitives (5 review findings, see SECURITY.md)
v0.6.0 ✅ released Bilingual i18n out of the box — ersan.i18n with English + Turkish locales, ERSAN_LANG env var, packaged via importlib.resources (US-008). Adds structlog as a runtime dep (first adopter; repo-wide migration tracked as US-011)
Version Status Goal
v0.x — next planned Inbox MVP — Microsoft Graph OAuth via MSAL device-code flow, ~/.ersan/tokens.json storage, first bundled Outlook toolset (US-007)
v0.x — later planned OpenTelemetry runtime instrumentation (US-009); repo-wide structlog adoption (US-011); OPA-policy evaluation (US-012)

Configuration

ersan's runtime config is env-first — the source of truth is ersan.settings.LLMSettings. Every config field maps to one ERSAN_LLM_* env var.

Local Ollama example:

export ERSAN_LLM_PROVIDER=ollama
export ERSAN_LLM_MODEL=llama3
export ERSAN_LLM_BASE_URL=http://localhost:11434/v1

Anthropic example:

export ERSAN_LLM_PROVIDER=anthropic
export ERSAN_LLM_MODEL=claude-3-5-sonnet-latest
export ERSAN_LLM_API_KEY=$ANTHROPIC_API_KEY

Run ersan config to see what the runtime resolved from your env (the API key is masked as "***"). Run ersan config --schema to print the JSON Schema. See docs/configuration.md for the full env surface.

How ersan is built

ersan is maintained by Ersan Bilik with AI coding assistants coordinated through GitHub Spec-Kit and a model-pinned multi-agent dev cycle (D-019). Every release ships through the same flow: spec → plan → tasks → implement → 2-way red-team review → fix → merge → architect-owned sole-truth gate → release.

Get involved

License

Apache 2.0. See LICENSE.

Built by Ersan Bilik.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ersan-0.6.0.tar.gz (87.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ersan-0.6.0-py3-none-any.whl (64.4 kB view details)

Uploaded Python 3

File details

Details for the file ersan-0.6.0.tar.gz.

File metadata

  • Download URL: ersan-0.6.0.tar.gz
  • Upload date:
  • Size: 87.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ersan-0.6.0.tar.gz
Algorithm Hash digest
SHA256 1e0f28fe835c23bd7a75f6f27045ec67dc2db73fc0bf9d2d731d9403af0b4aa5
MD5 432269816d9e62d6c29a4fe0a630d599
BLAKE2b-256 bea7f9932e437d0a6565ed7639a09c5c2a6c99597e7b7ec95653e505cb0a4e8a

See more details on using hashes here.

Provenance

The following attestation bundles were made for ersan-0.6.0.tar.gz:

Publisher: release.yml on ersan-ai/ersan

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ersan-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: ersan-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 64.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ersan-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1ec9d1a26fca1bd3602938cdbd8ae4d62ea9a269e12b3153aeb26625be4ae3fb
MD5 123525df8d32b70faf2cdf06d33ec6eb
BLAKE2b-256 bf729ab6e9bbc661f0b1e1bce9584d18aef132a27f23e1ff7d3f5de5f4165f33

See more details on using hashes here.

Provenance

The following attestation bundles were made for ersan-0.6.0-py3-none-any.whl:

Publisher: release.yml on ersan-ai/ersan

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page