pushary-crewai
Phone approvals for CrewAI agents. Your agent asks, your user taps Approve or Deny.
Full walkthrough: Human-in-the-loop for CrewAI
What you need
- A Pushary Partner plan, from $99 a month. Start the trial.
- An API key from Partner onboarding, set as
PUSHARY_API_KEY. - Your users install the free Pushary app (iPhone, Android). They never sign up or pay.
Quick start
pip install pushary-crewai
export PUSHARY_API_KEY=pk_xxx.sk_xxx
from crewai import Agent, Task, Crew
from pushary_crewai import connect, make_ask_human_tool
link = connect("user_123") # once per user: show them this link
agent = Agent(
role="Ops",
goal="Ship safely",
backstory="Careful operator.",
tools=[make_ask_human_tool("user_123")],
)
task = Task(
description="Draft the release. Before finalizing, call ask_human to get approval.",
expected_output="approved release notes",
agent=agent,
)
Crew(agents=[agent], tasks=[task]).kickoff()
This replaces the console human_input=True prompt. The tool waits until the person
answers on their phone. A no, or no answer, tells the agent not to proceed. The
external_id is bound when you build the tool, never taken from the model, so a
prompt-injected agent cannot ask the wrong person.
CrewAI's own docs on this: Human feedback in Flows.
Lower-level helpers
from pushary_crewai import ask_human
d = ask_human("Approve this refund?", external_id="user_123", type="confirm")
if d["approved"]:
issue_refund()
API
connect(external_id, *, api_key=None, base_url=None): enroll an end-user's phone.make_ask_human_tool(external_id, *, name=..., ...): a CrewAIBaseToolbound to that user.ask_human(question, *, external_id, type="confirm", ...): blocking, returns the decision dict.resolve_pushary_callback(raw_body, signature, secret): verify + parse a callback for a durable path.describe_answer(type, result),is_affirmative(answer),deterministic_key(parts),SIGNATURE_HEADER.
Example
The basic example gives an agent a blocking ask-human tool.
The Flow example uses CrewAI's native
@human_feedback(provider=...) path. It creates a Pushary decision, saves the
pending Flow, and exits. A later command reads the decision from Pushary and
resumes the same Flow. No model key or open worker is needed. Tested with
crewai==1.15.22 and pushary==2.1.1.
python -m pip install -e . 'crewai==1.15.22'
export PUSHARY_API_KEY='your Partner server key'
export PUSHARY_EXTERNAL_ID='your enrolled customer ID'
export CREWAI_STORAGE_DIR="$(mktemp -d)"
python examples/flow_feedback.py start 'Send the release note'
# Answer on the connected phone. Copy flow_id and decision_id from the output.
python examples/flow_feedback.py resume FLOW_ID DECISION_ID \
--database "$CREWAI_STORAGE_DIR/resumes.sqlite"
Keep CREWAI_STORAGE_DIR and the resume database across processes. A pending
decision returns pending; a decline or expiry returns approved: false.
The example checks the decision ID, exact question, Flow, and recipient before
resuming. Its SQLite claim prevents two local workers from resuming the same
Flow concurrently; a failed or interrupted resume stays claimed for manual
inspection. Use shared transactional storage across hosts.
The Flow only returns the review result. If you attach a business action,
bind its exact arguments and recipient in your application, and make the
action idempotent. Do not treat a model's approval claim or a direct call to
flow.resume() as authorization.
License
MIT
Metadata
Release files for pushary-crewai 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pushary_crewai-0.3.1.tar.gz | 9.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pushary_crewai-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 15.2 kB
Release files / pushary_crewai-0.3.1.tar.gz
| Download URL | pushary_crewai-0.3.1.tar.gz |
|---|---|
| Size | 9.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9dd60edb6dfe9a2bb6e27401eb0534ea1ffec8e97f96c0b97628cb214cb3c104
|
|
BLAKE2b-256 checksum How to use checksums |
077f2e61501cd001e798a0ac45f175fbcb100f94353544915ee214efdeacfee8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.
Transparency logRelease files / pushary_crewai-0.3.1-py3-none-any.whl
| Download URL | pushary_crewai-0.3.1-py3-none-any.whl |
|---|---|
| Size | 5.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
54b5356bf2c8a72dfd672425941dc0c7898d83d8e7090ca2e8b42709dc4ff54e
|
|
BLAKE2b-256 checksum How to use checksums |
92cd8488290abc04fadc7c5b26e40ce35362998e812bf5095a3361b1e3861b20
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.
Transparency log