Skip to content

Commit cb1b772

Browse files
ejentumclaude
andcommitted
Initial release: crewai-ejentum v0.1.0
Standalone PyPI package replacing the closed crewAIInc/crewAI#5768 PR per CrewAI's tool-publishing guide (third-party tools live as their own crewai-prefixed PyPI packages, not in the CrewAI monorepo). EjentumHarnessTool wraps the Ejentum Logic API: each call retrieves a task-matched cognitive operation from a library of 679 across four harnesses (reasoning, code, anti-deception, memory). Each operation is engineered in two layers: a natural-language procedure (named failure pattern, executable steps, suppression vectors, falsification test) and an executable reasoning topology (graph DAG with decision gates, parallel branches, and meta-cognitive exit nodes that let the model pause to self-observe and re-enter). Eight unit tests cover the failure surface: missing API key, invalid mode, missing query, whitespace-only query (the path that previously could leak a paid request), success-path response parsing, 401 path, unexpected response shape, non-string scaffold value, and network error. Build: hatchling, src/ layout, Python 3.10-3.13 (CrewAI does not yet support 3.14). Release workflow uses PyPI OIDC Trusted Publisher via pypa/gh-action-pypi-publish with attestations enabled. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 parents  commit cb1b772

11 files changed

Lines changed: 693 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
fail-fast: false
14+
matrix:
15+
python-version: ['3.10', '3.11', '3.12']
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Setup Python ${{ matrix.python-version }}
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: ${{ matrix.python-version }}
23+
cache: pip
24+
25+
- name: Install build + dev deps
26+
run: |
27+
python -m pip install --upgrade pip
28+
pip install -e ".[dev]"
29+
30+
- name: Lint
31+
run: ruff check src tests
32+
33+
- name: Run tests
34+
run: pytest -v
35+
36+
- name: Build sdist + wheel (sanity check)
37+
run: python -m build
38+
39+
- name: Verify wheel contents
40+
run: |
41+
ls -la dist/
42+
python -m zipfile -l dist/*.whl | head -30

.github/workflows/release.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Publish to PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
permissions:
9+
contents: read
10+
id-token: write
11+
12+
jobs:
13+
publish:
14+
runs-on: ubuntu-latest
15+
environment:
16+
name: pypi
17+
url: https://pypi.org/project/crewai-ejentum/
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v4
21+
22+
- name: Setup Python
23+
uses: actions/setup-python@v5
24+
with:
25+
python-version: '3.12'
26+
27+
- name: Install build deps
28+
run: |
29+
python -m pip install --upgrade pip
30+
pip install build
31+
32+
- name: Verify version matches tag
33+
run: |
34+
PYPROJECT_VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
35+
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
36+
if [ "$PYPROJECT_VERSION" != "$TAG_VERSION" ]; then
37+
echo "::error::pyproject.toml version ($PYPROJECT_VERSION) does not match git tag ($TAG_VERSION). Bump pyproject.toml before tagging."
38+
exit 1
39+
fi
40+
echo "Version match OK: $PYPROJECT_VERSION"
41+
42+
- name: Build sdist + wheel
43+
run: python -m build
44+
45+
- name: List built artifacts
46+
run: ls -la dist/
47+
48+
- name: Publish to PyPI (via Trusted Publisher OIDC)
49+
uses: pypa/gh-action-pypi-publish@release/v1
50+
with:
51+
attestations: true

.gitignore

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
__pycache__/
2+
*.pyc
3+
*.pyo
4+
*.pyd
5+
.pytest_cache/
6+
.ruff_cache/
7+
.coverage
8+
htmlcov/
9+
.tox/
10+
.venv/
11+
venv/
12+
env/
13+
*.egg-info/
14+
build/
15+
dist/
16+
.idea/
17+
.vscode/
18+
*.log
19+
.DS_Store
20+
.env
21+
.env.*
22+
!.env.example

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Changelog
2+
3+
All notable changes to `crewai-ejentum` are documented here. This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4+
5+
## [0.1.0] - 2026-05-11
6+
7+
### Added
8+
9+
- Initial release.
10+
- `EjentumHarnessTool` CrewAI tool wrapping the Ejentum Logic API. Single tool, four modes (`reasoning`, `code`, `anti-deception`, `memory`) selected per call via the `mode` argument.
11+
- `EjentumHarnessParams` pydantic schema declares `query` (required, non-empty) and `mode` (required, one of four).
12+
- Live API credential test happens implicitly on first call: a 401 surfaces an actionable error pointing the operator at <https://ejentum.com/pricing>.
13+
- Eight unit tests cover the failure surface: missing API key, invalid mode, missing query, whitespace-only query (the path that previously could leak a paid request), success-path response parsing, 401 path, unexpected response shape, non-string scaffold value, and network error.
14+
- Published to PyPI with OIDC trusted-publisher provenance attestation via GitHub Actions.
15+
16+
### Background
17+
18+
This package is the standalone-PyPI replacement for the closed [crewAIInc/crewAI#5768](https://github.com/crewAIInc/crewAI/pull/5768) PR. Per CrewAI's [tool-publishing guide](https://docs.crewai.com/en/guides/tools/publish-custom-tools), third-party tools live in their own PyPI packages with the `crewai-` prefix rather than in the CrewAI monorepo.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Ejentum
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# crewai-ejentum
2+
3+
A [CrewAI](https://crewai.com) tool that retrieves a task-matched **cognitive operation** from the [Ejentum](https://ejentum.com) Reasoning Harness and injects it into the agent's reasoning before it produces an answer.
4+
5+
Each operation in the Ejentum library (679 of them, organized across four harnesses) is engineered in **two layers**:
6+
7+
- a **natural-language procedure** the model can read, naming the steps to take and the failure pattern to refuse, and
8+
- an **executable reasoning topology**: a graph-shaped plan over those steps. The plan names explicit decision points where the model branches, parallel branches that run and rejoin, bounded loops that run until convergence, named meta-cognitive moments where the model is asked to stop, look at its own working, and re-enter at a specific step, and escape paths for when the prescribed plan stops fitting the task at hand.
9+
10+
The natural-language layer tells the model *what* to do. The topology layer pins down *how* those steps connect: where to decide, where to loop, where to stop and look at itself. Together they act as a persistent attention anchor that survives long context windows and multi-turn execution chains, which is precisely where a model's own reasoning template typically decays.
11+
12+
## Installation
13+
14+
```bash
15+
pip install crewai-ejentum
16+
```
17+
18+
## Configuration
19+
20+
Get a free Ejentum API key (100 calls, no card required) at <https://ejentum.com/pricing> and set it in your environment:
21+
22+
```bash
23+
export EJENTUM_API_KEY="zpka_..."
24+
```
25+
26+
## Usage
27+
28+
```python
29+
from crewai import Agent, Task, Crew
30+
from crewai_ejentum import EjentumHarnessTool
31+
32+
harness = EjentumHarnessTool()
33+
34+
architect = Agent(
35+
role="Senior architect",
36+
goal="Evaluate technical decisions honestly",
37+
backstory="You are pragmatic and push back on sunk-cost framings.",
38+
tools=[harness],
39+
)
40+
41+
task = Task(
42+
description=(
43+
"We've spent three months on the GraphQL gateway. It's mostly done. "
44+
"Should we keep going or pivot to REST? "
45+
"Call the Ejentum harness with mode='anti-deception' before answering."
46+
),
47+
agent=architect,
48+
expected_output="A recommendation that separates past spending from prospective evaluation.",
49+
)
50+
51+
Crew(agents=[architect], tasks=[task]).kickoff()
52+
```
53+
54+
## The four harnesses
55+
56+
Pick the mode that matches what the agent is about to do:
57+
58+
| Mode | Best for | Library size |
59+
|---|---|---|
60+
| `reasoning` | Analytical, diagnostic, planning, multi-step tasks spanning abstraction, time, causality, simulation, spatial, and metacognition | 311 operations |
61+
| `code` | Code generation, refactoring, review, and debugging across the software-engineering layer | 128 operations |
62+
| `anti-deception` | Prompts that pressure the agent to validate, certify, or soften an honest assessment, spanning sycophancy, hallucination, deception, adversarial framing, judgment, and executive control | 139 operations |
63+
| `memory` | Sharpening an observation already formed about cross-turn drift across the perception layer; filter-oriented, not write-oriented | 101 operations |
64+
65+
## What an injection looks like
66+
67+
A real `reasoning` mode response on the query `investigate why our nightly ETL job has started failing intermittently over the past two weeks; nothing in the code or schema has changed`:
68+
69+
```
70+
[NEGATIVE GATE]
71+
The server's response time was accepted as average, despite a suspicious
72+
rhythm break in its timing pattern.
73+
74+
[PROCEDURE]
75+
Step 1: Establish baseline timing profiles by extracting historical
76+
durations and intervals for each event type. Step 2: Compare each observed
77+
timing against its baseline and compute deviation magnitude. Step 3:
78+
Classify anomalies as too fast, too slow, too early, or too late, and rank
79+
by severity. ... Step 5: If deviation exceeds two standard deviations,
80+
probe root cause by tracing upstream dependencies. ...
81+
82+
[REASONING TOPOLOGY]
83+
S1:durations → FIXED_POINT[baselines] → N{dismiss_timing_deviations_
84+
without_investigation} → for_each: S2:compare → S3:deviation →
85+
G1{>2sigma?} --yes→ S4:classify → S5:probe_cause → FLAG → continue --no→
86+
S6:validate → continue → all_checked → OUT:anomaly_report
87+
88+
[TARGET PATTERN]
89+
Establish timing baselines by extracting historical response intervals.
90+
Compare current server response time to this baseline. ...
91+
92+
[FALSIFICATION TEST]
93+
If no event timing is flagged as suspiciously fast or slow relative to
94+
baseline, temporal anomaly detection was not active.
95+
96+
Amplify: timing baseline comparison; anomaly classification; security
97+
context elevation
98+
Suppress: average timing acceptance; outlier normalization
99+
```
100+
101+
The agent reads both the natural-language `[PROCEDURE]` and the graph-logic `[REASONING TOPOLOGY]` before generating its user-facing answer. The bracketed labels are instructions to the agent, not content to display; the user sees a naturally-phrased answer shaped by the injection.
102+
103+
## API reference
104+
105+
```python
106+
EjentumHarnessTool(api_url: str = "...", timeout_seconds: float = 10.0)
107+
```
108+
109+
| Field | Default | Description |
110+
|---|---|---|
111+
| `api_url` | `https://ejentum-main-ab125c3.zuplo.app/logicv1/` | Override only if you self-host the Ejentum Logic API gateway. |
112+
| `timeout_seconds` | `10.0` | Per-call HTTP timeout. |
113+
114+
`EJENTUM_API_KEY` is read from the environment at call time.
115+
116+
The tool's `_run` accepts two arguments:
117+
118+
- `query` (string, required): a 1-2 sentence description of the task the agent is about to work on. For `mode='memory'`, format as `"I noticed [X]. This might mean [Y]. Sharpen: [Z]."`.
119+
- `mode` (string, required): one of `reasoning`, `code`, `anti-deception`, `memory`.
120+
121+
Returns the scaffold string. Errors are returned as human-readable strings (the tool never raises so the agent never crashes the run).
122+
123+
## Compatibility
124+
125+
- Python 3.10+
126+
- `crewai>=0.40.0`
127+
- `requests>=2.31.0`
128+
129+
## Resources
130+
131+
- Ejentum homepage: <https://ejentum.com>
132+
- Free tier and pricing: <https://ejentum.com/pricing>
133+
- API reference: <https://ejentum.com/docs/api_reference>
134+
- "Why LLM Agents Fail" essay: <https://ejentum.com/blog/why-llm-agents-fail>
135+
- "Under Pressure" research paper: <https://doi.org/10.5281/zenodo.19392715>
136+
- CrewAI documentation: <https://docs.crewai.com>
137+
138+
## License
139+
140+
[MIT](./LICENSE)

pyproject.toml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
[build-system]
2+
requires = ["hatchling>=1.21"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "crewai-ejentum"
7+
version = "0.1.0"
8+
description = "CrewAI tool for the Ejentum Reasoning Harness. Each call retrieves a task-matched cognitive operation engineered in two layers: a natural-language procedure plus an executable reasoning topology (graph DAG with gates, parallel branches, and meta-cognitive exits). Injected before the LLM step to harden reasoning against decay on complex tasks and long agent loops."
9+
readme = "README.md"
10+
requires-python = ">=3.10,<3.14"
11+
license = "MIT"
12+
license-files = ["LICENSE"]
13+
authors = [
14+
{ name = "Ejentum", email = "info@ejentum.com" },
15+
]
16+
keywords = [
17+
"crewai",
18+
"crewai-tools",
19+
"ejentum",
20+
"reasoning-harness",
21+
"agentic-ai",
22+
"llm",
23+
"anti-deception",
24+
"cognitive-scaffold",
25+
"ai",
26+
]
27+
classifiers = [
28+
"Development Status :: 4 - Beta",
29+
"Intended Audience :: Developers",
30+
"License :: OSI Approved :: MIT License",
31+
"Operating System :: OS Independent",
32+
"Programming Language :: Python :: 3",
33+
"Programming Language :: Python :: 3.10",
34+
"Programming Language :: Python :: 3.11",
35+
"Programming Language :: Python :: 3.12",
36+
"Programming Language :: Python :: 3.13",
37+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
38+
"Topic :: Software Development :: Libraries :: Python Modules",
39+
]
40+
dependencies = [
41+
"crewai>=0.40.0",
42+
"requests>=2.31.0",
43+
"pydantic>=2.0.0",
44+
]
45+
46+
[project.urls]
47+
Homepage = "https://ejentum.com"
48+
Documentation = "https://ejentum.com/docs/api_reference"
49+
Repository = "https://github.com/ejentum/crewai-ejentum"
50+
Issues = "https://github.com/ejentum/crewai-ejentum/issues"
51+
Changelog = "https://github.com/ejentum/crewai-ejentum/blob/main/CHANGELOG.md"
52+
Pricing = "https://ejentum.com/pricing"
53+
54+
[project.optional-dependencies]
55+
dev = [
56+
"pytest>=8.0.0",
57+
"pytest-cov>=5.0.0",
58+
"build>=1.2.0",
59+
"ruff>=0.6.0",
60+
]
61+
62+
[tool.hatch.build.targets.wheel]
63+
packages = ["src/crewai_ejentum"]
64+
65+
[tool.hatch.build.targets.sdist]
66+
include = [
67+
"src/crewai_ejentum",
68+
"tests",
69+
"README.md",
70+
"LICENSE",
71+
"CHANGELOG.md",
72+
"pyproject.toml",
73+
]
74+
75+
[tool.pytest.ini_options]
76+
testpaths = ["tests"]
77+
python_files = ["test_*.py"]
78+
pythonpath = ["src"]
79+
80+
[tool.ruff]
81+
line-length = 100
82+
target-version = "py310"

src/crewai_ejentum/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""crewai-ejentum: CrewAI tool for the Ejentum Reasoning Harness.
2+
3+
Exposes :class:`EjentumHarnessTool` as an agent-callable CrewAI tool. Each call
4+
retrieves a task-matched cognitive operation from a library of 679, engineered in
5+
two layers: a natural-language procedure plus an executable reasoning topology
6+
(graph DAG with gates, parallel branches, and meta-cognitive exit nodes). The
7+
calling LLM ingests both layers before writing.
8+
9+
Free tier: 100 calls, no card required, at https://ejentum.com/pricing.
10+
"""
11+
12+
from crewai_ejentum.tool import EjentumHarnessTool
13+
from crewai_ejentum.schemas import EjentumHarnessParams, HarnessMode
14+
15+
__all__ = ["EjentumHarnessTool", "EjentumHarnessParams", "HarnessMode"]
16+
__version__ = "0.1.0"

0 commit comments

Comments
 (0)