Skip to main content

Build any specialist LLM agent declaratively. Persona, frameworks, probes, red flags, and themes as data — you get a typed, cited, safety-aware agent. Domain-agnostic, provider-agnostic.

Project description

personakit

Build any specialist LLM agent declaratively. Describe a role — persona, frameworks, probes, red flags, recommendation themes — as a single data object, and get a typed, cited, safety-aware agent. No chain wiring, no graph building, no orchestration code.

Works with any LLM provider. Domain-agnostic: engineering, fintech, customer support, product, legal, clinical, education, delivery — one library, one pattern.

Created by Majidul Islam.

pip install personakit

The idea

A specialist agent is rarely about retrieval — it's about role, tone, knowledge frameworks, diagnostic questions, safety triggers, and output shape. All of that can be captured declaratively:

  • A code reviewer has frameworks (OWASP, SOLID), probes (does it have tests? what's the blast radius?), and red flags (hard-coded secrets, SQL injection).
  • A fintech compliance officer has frameworks (AML/BSA, OFAC, FATF typologies), probes (amount, country pair, velocity), and red flags (sanctioned counterparty, structuring).
  • A customer support triage agent has frameworks (refund policy, escalation matrix), probes (order ID, sentiment), and red flags (chargeback language, data request).
  • A scrum master has frameworks (Scrum Guide, DORA), probes (days remaining, WIP count), and red flags (scope creep, external blocker without owner).

personakit turns that shape into a library. One Specialist object = one declarative agent. Ship it via Python, or hand a YAML file to a domain expert and let them author without touching any chain code.

The distinctive primitives:

Concept What it gives you
Specialist Frozen dataclass — the entire agent definition, authorable in YAML
Framework Body of knowledge with a citation key, cited in output
Probe Diagnostic question; becomes a typed field in the structured response
RedFlag Trigger → severity → action → citation, matched deterministically AND semantically
Theme User-selectable recommendation category
Priority Always-on checks reported as met / unmet / unknown
Tool (optional) @tool decorator — opt-in for external memory, DB, APIs

Core has just two runtime deps: pydantic and httpx.


Quickstart — any domain in 20 lines

import asyncio
from personakit import Agent, Specialist, Framework, Probe, RedFlag, Severity, Theme

product_manager = Specialist(
    name="product_manager",
    display_name="Senior Product Manager",
    persona="You are a senior B2B SaaS PM. You sharpen feature specs and find edge cases.",
    frameworks=[Framework(name="Jobs-to-be-Done"), Framework(name="RICE scoring")],
    probes=[
        Probe(question="What is the user's job-to-be-done?"),
        Probe(question="What is the current workaround cost?", value_type="string"),
        Probe(question="Is there a measurable success metric proposed?",
              value_type="boolean", weight="high"),
    ],
    red_flags=[
        RedFlag(
            trigger="No success metric defined",
            severity=Severity.HIGH,
            action="Block PRD review. Require a quantitative success metric before scoping.",
        ),
    ],
    themes=[Theme(name="Refinements"), Theme(name="Edge cases"), Theme(name="Open questions")],
)

agent = Agent(specialist=product_manager, model="gpt-4o-mini")

async def main():
    result = await agent.analyze(
        "PRD: Add a 'dark mode' toggle to settings. Shipping next quarter."
    )
    print(result.pretty())

asyncio.run(main())

Bundled specialists across domains

from personakit.examples import (
    CODE_REVIEWER,                  # engineering — PRs, OWASP, SOLID
    CONTRACT_REVIEWER,              # legal — M&A redlines, GDPR
    CUSTOMER_SUPPORT_TRIAGE,        # support — SaaS B2C, refund policy, escalation
    FALLS_PREVENTION_NURSE,         # clinical — NICE guidelines, post-fall protocol
    FINTECH_TRANSACTION_REVIEWER,   # finance — AML/fraud, OFAC, FATF typologies
    MATH_TUTOR,                     # education — Socratic, minimal shape
    SCRUM_MASTER,                   # delivery — sprint health, blockers, WIP limits
)

Each one is a template. Copy, edit, ship your own.

Real agent types you can build in one file

You want an agent that... Define these concepts
Reviews pull requests for security and correctness Framework(OWASP), RedFlag(sql_injection, hardcoded_secret), Theme(Security, Performance)
Screens fintech transactions for AML / sanctions Framework(BSA/AML, OFAC), RedFlag(sanctioned_counterparty, structuring), typology Themes
Triages customer support messages Probe(order_id, sentiment), RedFlag(chargeback_language), Theme(Resolution, Escalation)
Coaches a sprint team as a scrum master Framework(Scrum Guide, DORA), RedFlag(scope_creep, external_blocker), Theme(At-risk stories, Retro candidates)
Reviews M&A contracts for legal risk Framework(English common law, UCC), RedFlag(unlimited_liability), Theme(Liability, IP)
Runs a post-fall clinical assessment Framework(NICE NG161, NICE CG176), RedFlag(LOC, head_contact_on_anticoagulant), clinical probes
Writes product specs against JTBD Framework(Jobs-to-be-Done, RICE), RedFlag(no_success_metric), Theme(Edge cases, Open questions)
Tutors a student without giving away answers Theme(Concept check, Next hint, Common pitfall), Constraint(no direct answer first)
Does equity research on a public SaaS name Framework(DCF, Rule of 40), RedFlag(NDR_below_100, negative_fcf_plus_decel), Theme(Thesis, Risks)

YAML authoring — hand off to a domain expert

name: code_reviewer
persona: Senior staff engineer reviewing PRs. Correctness, security, perf, in that order.
frameworks: [OWASP Top 10, SOLID, 12-Factor App]
probes:
  - question: Does the change include tests?
    key: has_tests
    value_type: boolean
    weight: high
red_flags:
  - trigger: Hard-coded secret or API key
    severity: critical
    action: BLOCK merge. Rotate the secret. Move to a secret manager.
    match: both
    patterns: ['sk-[A-Za-z0-9]{20,}', 'AKIA[0-9A-Z]{16}']
themes: [Correctness, Security, Performance, Maintainability, Tests]
from personakit import Specialist, Agent

spec = Specialist.from_yaml("code_reviewer.yaml")
agent = Agent(specialist=spec, model="claude-sonnet-4-6")

Red flags — the feature no-one else has

Every RedFlag is a trigger → severity → action → citation contract, matched in two phases:

  1. Deterministic pre-match — regex / keywords on raw input. Fast, offline, quotable.
  2. Semantic post-match — the LLM evaluates whether the trigger applies in context. Catches paraphrase, synonyms, implicit meaning.

Results merge, with deterministic evidence winning on ties:

RedFlag(
    trigger="Hard-coded secret, token, or credential",
    severity=Severity.CRITICAL,
    action="BLOCK merge. Rotate secret. Move to secret manager.",
    citation="OWASP A02:2021",
    match=MatchMode.BOTH,
    patterns=[r"sk-[A-Za-z0-9]{20,}", r"AKIA[0-9A-Z]{16}"],
)

Structured output — derived from the Specialist

You never write a JSON schema by hand. The probes, red flags, and themes are the schema:

result = await agent.analyze(input_text)

result.summary                # narrative summary
result.probes_answered        # {probe_key: typed_value_or_null}
result.probes_unanswered      # list[Probe] — next-round questions
result.red_flags_triggered    # list[TriggeredRedFlag] with evidence + source
result.recommendations        # themed list with citations
result.citations_used         # framework citation keys referenced
result.priorities_status      # per-priority met / unmet / unknown
result.has_urgent             # convenience boolean

Tools — opt-in, for external memory & APIs

Core has zero coupling to tool calling. When you want tools, decorate functions and attach:

from personakit.tools import tool

@tool
def lookup_order(order_id: str) -> dict:
    """Fetch an order from the order database."""
    return order_db.get(order_id)

@tool
def search_knowledge_base(query: str, top_k: int = 5) -> list[str]:
    """Semantic search against the internal KB — your vector store."""
    return kb.search(query, k=top_k)

support_agent = Agent(specialist=CUSTOMER_SUPPORT_TRIAGE, model="gpt-4o-mini")
support_agent = support_agent.with_tools([lookup_order, search_knowledge_base])

OpenAI and Anthropic tool-calling happen through the same interface. Schemas are auto-built from your function signatures and docstrings.

Registry — one app, many specialists

from personakit import SpecialistRegistry

registry = SpecialistRegistry.from_directory("personas/")

# Route by domain
engineering_agents = registry.by_domain("engineering")
finance_agents = registry.by_domain("finance")

# Route by name
support = registry.get("support_triage")

Providers

Extra Install Default model
personakit[openai] openai>=1.0 gpt-4o-mini
personakit[anthropic] anthropic>=0.20 claude-sonnet-4-6
personakit[yaml] pyyaml>=6.0
personakit[all] all of the above

MockProvider ships in the core for offline testing — no API key needed:

from personakit.testing import MockProvider
provider = MockProvider(responses={"summary": "...", "recommendations": [...]})

Testing helpers

from personakit.testing import assert_triggered, assert_cited

result = await agent.analyze("Customer: 'I want to chargeback this transaction.'")
assert_triggered(result, "legal_or_chargeback_language_attorney_lawsuit_chargeback_small_claims_bbb")

Design principles

  1. Specialist is pure data. No behaviour, no side effects, serializable.
  2. Schema is derived. Probes, red flags, themes are the output contract.
  3. Deterministic where possible, semantic where needed. Red flags run both.
  4. Tools are opt-in. Core has zero coupling to tool calling.
  5. Minimal dependencies. pydantic + httpx. Everything else is an extra.
  6. Domain-neutral. Engineering, support, fintech, legal, clinical, education, delivery, product — one library.
  7. Provider-agnostic. Same Specialist, any model.

Works alongside the rest of the LLM toolchain

personakit focuses on declarative specialist definition. It intentionally does not try to be:

  • a chain-composition library — use LangChain when you need to wire up complex multi-step LLM pipelines
  • a multi-agent orchestration framework — use CrewAI when you need a team of agents collaborating on a shared goal
  • a branching control-flow engine — use LangGraph when you need conditional routing and loops across nodes

They compose nicely. A LangChain chain can invoke a personakit Agent as one of its steps. A CrewAI crew member can be a personakit Specialist. A LangGraph node can call agent.analyze() and route on result.has_urgent.

Use personakit for what it's best at — the declarative specialist layer — and reach for the others when the problem actually needs chains, crews, or graphs.

Status

Alpha — API may evolve. See CHANGELOG.md.

Author

Majidul Islam@Majidul17068

personakit is an independent open-source project. Contributions welcome.

License

MIT © 2026 Majidul Islam.

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

personakit-0.1.2.tar.gz (41.1 kB view details)

Uploaded Source

Built Distribution

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

personakit-0.1.2-py3-none-any.whl (47.6 kB view details)

Uploaded Python 3

File details

Details for the file personakit-0.1.2.tar.gz.

File metadata

  • Download URL: personakit-0.1.2.tar.gz
  • Upload date:
  • Size: 41.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for personakit-0.1.2.tar.gz
Algorithm Hash digest
SHA256 d0cb108607292d7d6749788237900dade291f803519c1bac5db6e76e011edebd
MD5 c7ca23531e7590e0e109499eac7cef97
BLAKE2b-256 b182e21a5434e5cb6dad92f7800ca04e1017fe3abd409c660278e09a0d1781e7

See more details on using hashes here.

File details

Details for the file personakit-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: personakit-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 47.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.8

File hashes

Hashes for personakit-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7732c8ba82749967593e939f3d9ae4233e2d94283e9ecd1aba370d277b67d232
MD5 2bbb4ee4b94890ab1e50efc8fa47149e
BLAKE2b-256 30bdecfdaabc42e35416b251f82c5986dfdb951e1889f916841d53878cf452e6

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