Jev email intent workflow

September 16, 2026 ยท View on GitHub

A small async LangGraph workflow that sends a mocked email to TypeSafe's Jev model, receives a typed Choice (invoice or general), and routes to a demo handler. The handlers only set a destination in graph state; they do not send email or make payments.

flowchart LR
    START --> detect_intent[Jev: detect intent]
    detect_intent -->|invoice| handle_invoice[accounts_payable]
    detect_intent -->|general| handle_general[general_inbox]
    handle_invoice --> END
    handle_general --> END

Run

Requires Python 3.10+ and uv:

uv sync
# Create .env using .env.example as a guide; keep an existing .env.
# Set TYPESAFE_API_KEY to your TypeSafe key.
uv run python main.py
# Or run just one email:
uv run python main.py --email-id email-09

The input emails are mocked; classification makes real TypeSafe API calls (one per email). The default model is jev-1.12; override it with TYPESAFE_DEFAULT_MODEL if needed for your account. Output includes intent, confidence, both label probabilities, destination, model, and comparison against the expected label. API failures stop execution rather than assigning a fabricated intent.

data/mock_emails.json contains 10 labeled examples: five invoice requests and five general emails, including two general emails that mention invoices. invoice covers invoice delivery, copies, corrections, disputes, and payment follow-ups. general is the catch-all for other primary intents. Expected labels are used only for evaluation and never sent to Jev. These examples are a smoke check, not an accuracy benchmark.

The graph is in src/typesafe_ai_langgraph/typesafe_ai_langgraph_workflow.py. To use another email, call await build_workflow(client).ainvoke({"email": email}) with an email containing id, sender, subject, and body, while the async client is open. Confidence is exposed for inspection; this demo always routes to one of the two handlers.

Tests

uv run python -m unittest discover -s tests -v

Tests mock the SDK response and run the actual graph without credentials or network. They verify routing and input isolation, not Jev's semantic accuracy.

References: TypeSafe Python API, Choice, and LangGraph Graph API.