Skip to main content

NotiLens — unified SDK + CLI for AI agent notifications

Project description

NotiLens

Unified SDK + CLI for sending notifications from AI agents and any Python project to NotiLens.

Installation

pip install notilens

With framework auto-patching:

pip install notilens[openai]
pip install notilens[anthropic]
pip install notilens[all]        # all frameworks

Quick Start

CLI (hooks, shell scripts)

# Register your agent
notilens init --agent my-agent --token YOUR_TOKEN --secret YOUR_SECRET

# Use in scripts / Claude Code hooks
notilens task.start --agent my-agent --task job_001
notilens task.complete "All done" --agent my-agent --task job_001

Python SDK

import notilens

agent = notilens.init(agent="my-agent", token="YOUR_TOKEN", secret="YOUR_SECRET")

agent.task_start(task_id="job_001")
agent.task_complete("All done", task_id="job_001")

Python SDK with auto-patching

import notilens

agent = notilens.init(
    agent="my-agent",
    token="YOUR_TOKEN",
    secret="YOUR_SECRET",
    patch=True,   # auto-instruments OpenAI, Anthropic, LangChain, CrewAI, etc.
)

# Use OpenAI, Anthropic etc. normally — events fire automatically

Setup

Get your token and secret from the NotiLens dashboard.

CLI

notilens init --agent AGENT --token TOKEN --secret SECRET

SDK (env vars)

export NOTILENS_TOKEN=your_token
export NOTILENS_SECRET=your_secret
agent = notilens.init(agent="my-agent")  # reads from env

Multiple agents

notilens init --agent scraper --token TOKEN_A --secret SECRET_A
notilens init --agent mailer  --token TOKEN_B --secret SECRET_B
scraper = notilens.init(agent="scraper", token="TOKEN_A", secret="SECRET_A")
mailer  = notilens.init(agent="mailer",  token="TOKEN_B", secret="SECRET_B", patch=True)

Only one agent can own patch=True — raises if more than one tries.


CLI Reference

Task Lifecycle

notilens task.start    --agent AGENT [--task ID]
notilens task.progress "msg"  --agent AGENT --task ID
notilens task.loop     "msg"  --agent AGENT --task ID
notilens task.retry    --agent AGENT --task ID
notilens task.stop     --agent AGENT --task ID
notilens task.complete "msg"  --agent AGENT --task ID
notilens task.error    "msg"  --agent AGENT --task ID
notilens task.fail     "msg"  --agent AGENT --task ID
notilens task.timeout  "msg"  --agent AGENT --task ID
notilens task.cancel   "msg"  --agent AGENT --task ID
notilens task.terminate "msg" --agent AGENT --task ID

Input / Human-in-the-loop

notilens input.required "Please confirm" --agent AGENT --task ID
notilens input.approve  "Approved"       --agent AGENT --task ID
notilens input.reject   "Rejected"       --agent AGENT --task ID

AI Response

notilens ai.response.generate "Summary ready" --agent AGENT --task ID
notilens ai.response.fail     "Model error"   --agent AGENT --task ID

Generic Event

Emit any custom event — works for non-AI projects too:

notilens emit user.registered "New signup" --agent AGENT
notilens emit disk.space.full "Only 2GB left" --agent AGENT
notilens emit order.placed "Order #1234" --agent AGENT

Agent Management

notilens agents                           # list configured agents
notilens remove-agent AGENT              # remove an agent
notilens version

SDK Reference

notilens.init()

agent = notilens.init(
    agent="my-agent",         # agent name (required)
    token="...",              # NotiLens token (or NOTILENS_TOKEN env var)
    secret="...",             # NotiLens secret (or NOTILENS_SECRET env var)
    patch=False,              # auto-patch AI frameworks
    min_level="info",         # minimum event level to send
    loop_threshold=10,        # AI calls within loop_window before loop alert
    loop_window=60.0,         # time window in seconds for loop detection
    call_timeout=30.0,        # alert if AI call exceeds this many seconds
    silent=False,             # suppress SDK log output
    debug=False,              # enable verbose logging
)

Task Lifecycle

task_id = agent.task_start(task_id="job_001")   # task_id auto-generated if omitted
agent.task_progress("Step 2 of 5", task_id=task_id)
agent.task_loop("Processing item 42", task_id=task_id)
agent.task_retry(task_id=task_id)
agent.task_stop(task_id=task_id)
agent.task_complete("Done", task_id=task_id)
agent.task_error("Step failed", task_id=task_id)
agent.task_fail("Unrecoverable", task_id=task_id)
agent.task_timeout("Exceeded limit", task_id=task_id)
agent.task_cancel("User cancelled", task_id=task_id)
agent.task_terminate("OOM", task_id=task_id)

Input / Human-in-the-loop

agent.input_required("Confirm before proceeding", task_id=task_id)
agent.input_approved("User confirmed", task_id=task_id)
agent.input_rejected("User rejected", task_id=task_id)

AI Response

agent.ai_response_generated("Summary ready", task_id=task_id)
agent.ai_response_failed("Model unavailable", task_id=task_id)

Generic Emit

agent.emit("user.registered", "New signup", meta={"plan": "pro"})
agent.emit("disk.space.full", "Only 2GB left", level="warning")
agent.emit("order.placed", "Order #1234", meta={"amount": 99.99})

CLI Options

Flag Description
--agent NAME Agent name (required)
--task ID Task ID (auto-generated if omitted)
--level Override level: debug info warning error
--meta key=value Custom metadata (repeatable)
--image_url URL Attach an image
--open_url URL Link to open
--download_url URL Link to download
--tags "tag1,tag2" Comma-separated tags
--is_actionable true|false Override actionable flag
--confidence 0.0-1.0 Confidence score

Events

Event Level Description
task.started info Task began
task.progress info Mid-run update
task.loop warning Loop iteration
task.retrying warning Retry attempt
task.completed info Task finished successfully
task.stopped info Manually stopped
task.failed error Task failed
task.error error Non-fatal error
task.timeout error Exceeded time limit
task.cancelled warning Task cancelled
task.terminated error Force-terminated
ai.call.start info AI framework call began
ai.call.complete info AI framework call finished
ai.response.generated info AI produced a response
ai.response.failed error AI failed to respond
input.required warning Waiting for human input
input.approved info Input approved
input.rejected warning Input rejected

Full Example

# Register
notilens init --agent summarizer --token my_token --secret my_secret

# Run a job
notilens task.start --agent summarizer --task job_42
notilens task.progress "Fetching document" --agent summarizer --task job_42
notilens task.complete "Summary ready" --agent summarizer --task job_42 \
  --open_url https://example.com/summary.pdf \
  --meta pages=12
import notilens
import openai

agent = notilens.init(
    agent="summarizer",
    token="my_token",
    secret="my_secret",
    patch=True,
)

task_id = agent.task_start()
try:
    # OpenAI call tracked automatically
    response = openai.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": "Summarise this document..."}],
    )
    agent.ai_response_generated(response.choices[0].message.content[:80], task_id=task_id)
    agent.task_complete("Summary done", task_id=task_id)
except Exception as e:
    agent.task_fail(str(e), task_id=task_id)

License

MIT — notilens.com

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

notilens-0.2.0.tar.gz (17.0 kB view details)

Uploaded Source

Built Distribution

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

notilens-0.2.0-py3-none-any.whl (20.4 kB view details)

Uploaded Python 3

File details

Details for the file notilens-0.2.0.tar.gz.

File metadata

  • Download URL: notilens-0.2.0.tar.gz
  • Upload date:
  • Size: 17.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for notilens-0.2.0.tar.gz
Algorithm Hash digest
SHA256 de36b626f685cb072bffce6ed7bac28e608da2193bf5ad5aedbb1303271f6761
MD5 a13acf2238a990892c97666bf6a09f85
BLAKE2b-256 312bacc161be387f6757ee8a052d123e04f0808518dfb8b9498c604632b97dfc

See more details on using hashes here.

File details

Details for the file notilens-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: notilens-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 20.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for notilens-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 047ede0a070cf095a4163f323b9b49e5cc391f449e8ab7c5710407c21a674045
MD5 52d30fc3b5ba8bb15f3398ecacc26e68
BLAKE2b-256 dc4d05fdde9df153f67be5eec9ff6c2d9f46cec33df1289d03239a4ccc5f3f90

See more details on using hashes here.

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