Local Assync Agent (OpenAI Agents SDK)¶
assync-agent is a small local CLI that lets you ask natural-language
questions about a registered Assync project and get an answer grounded
exclusively in Assync's own read-only MCP tools. It is built on OpenAI's
Agents SDK (openai-agents)
and talks to the same local assync mcp stdio server that ChatGPT's
Developer Mode integration uses (see
ChatGPT Developer Mode) -- nothing about the
server changes for this client.
Want zero manual setup instead?
assync-agent requires a second terminal running
scripts/run-mcp-server.sh by hand and an exported OPENAI_API_KEY.
assync chat (built on top of this same client -- see
Chat & Setup) starts the MCP server itself, reads
the key from the macOS Keychain, and exits when done. Everything on
this page about the read-only guarantee, tool filter, and tracing
applies identically to both.
You
↓
OpenAI Agents SDK (Agent + Runner, running locally)
↓
OpenAI model, over the OpenAI API
↓
Assync MCP server (scripts/run-mcp-server.sh, stdio, unchanged)
↓
Project · Mission · Handoff · Decision · Audit
How this differs from the ChatGPT Developer Mode integration¶
The ChatGPT integration runs inside ChatGPT's own web UI, using your ChatGPT account and (for Developer Mode) a Secure MCP Tunnel. This client is a separate, local, standalone application: your own process, calling the OpenAI API directly with your own API key. Its usage is billed separately, as OpenAI API usage -- a ChatGPT Plus/Pro subscription does not include API credits. Both approaches connect to the exact same unmodified local MCP server; you can use either, or both, independently.
Setup¶
Install the extra (adds openai-agents on top of the existing mcp
extra used by the server side):
Set your API key in the environment -- never in a file inside this repository, never as a command-line argument, never committed:
Running it¶
.venv/bin/assync-agent "Where does project_assync currently stand?"
.venv/bin/assync-agent --project-id project_assync "Show completed missions"
By default stdout prints only the agent's final answer; diagnostics (and
any error) go to stderr, with a non-zero exit code on any startup, MCP, or
model/tool failure. A missing OPENAI_API_KEY produces OPENAI_API_KEY_REQUIRED
and exits before any request is made.
Example questions:
- "Where does project_assync currently stand?"
- "List the missions for project_assync and say which are completed."
- "What execution handoffs exist for project_assync, and what state are they in?"
- "What decisions are still pending for project_assync?"
Model¶
The default model is gpt-5.4-mini (the Agents SDK's own recommended
low-latency default for tool-using agents at the time this was written).
Override it with:
Read-only guarantee¶
This client can only ever reach 7 tools, enforced through the Agents SDK's
own MCP tool filter (create_static_tool_filter, see
src/assync/agent_client/mcp.py) -- not merely through the agent's prompt
instructions:
assync_status_showassync_mission_listassync_mission_showassync_execution_handoff_listassync_execution_handoff_showassync_decision_listassync_decision_show
Every other tool the MCP server exposes (mission/decision/handoff
mutations, authorization minting, project registration, and so on) is
never listed to the model in the first place. If a model attempts to call
a filtered-out tool anyway (e.g. via a prompt-injection attempt), the
Agents SDK raises ModelBehaviorError: Tool <name> not found before the
call ever reaches the real MCP server -- verified directly against the
real server in tests/test_agent_client_workflow.py::test_blocked_mutating_tool_call_fails_closed_with_no_mutation
and exercised again as eval cases 7 and 8. No Authorization is created, no
Decision is resolved, no Handoff is accepted, no Mission is transitioned
by this client, ever.
Tracing¶
The Agents SDK enables tracing by default and exports run traces (model
calls, tool calls, MCP activity) to OpenAI's backend
(platform.openai.com/traces) using the same OPENAI_API_KEY. Disable it
locally if you don't want that:
Assync's own Audit log and the Agents SDK's tracing are separate systems that must not be conflated: Audit records Assync governance events (mission/decision/handoff state), tracing records model/tool execution inside a single agent run. This client does not write anything to tracing beyond what the SDK does by default, and does not implement a second tracing system.
Known limitations¶
- No conversation memory across invocations -- each
assync-agentcall is one independent question and one independent Agent run. - No streaming output -- the CLI waits for the full run and prints the final answer.
- Model answers about mission/decision/handoff content are only as good as the model's summarization of the real tool output; the underlying data itself is always the real, current Assync state (never invented), but phrasing is not deterministic.
Running the tests¶
Offline (no OpenAI API calls, no cost) -- config/CLI, MCP tool-filter and lifecycle (against the real local server), and fake-model workflow tests:
/path/to/isolated/python3.11/bin/python -m pytest \
tests/test_agent_client_config.py \
tests/test_agent_client_cli.py \
tests/test_agent_client_mcp.py \
tests/test_agent_client_workflow.py
(Use this repository's isolated architecture-consistent Python 3.11 environment, not the machine's global interpreter -- see Installation.)
Running the real API smoke test¶
Requires OPENAI_API_KEY. Calls the real OpenAI API once:
export OPENAI_API_KEY="sk-..."
.venv/bin/assync-agent "Use Assync to report where project_assync currently stands."
Verify the answer's project id, branch, and HEAD against a direct
read-only check (assync status --json) to confirm the tool result was
genuinely used, not invented.
Running the evals¶
evals/assync_agent/ contains 8 cases (project status; missions;
handoffs; decisions; unknown project; unsupported question; a
prompt-injection attempt asking for a mutating tool call; a request to
accept a handoff). Requires OPENAI_API_KEY and calls the real OpenAI
API once per case (8 calls total) -- real, small usage cost, no mocked
model:
export OPENAI_API_KEY="sk-..."
/path/to/isolated/python3.11/bin/python -m evals.assync_agent.run_evals
Grading is criteria-based (expected tool category used, forbidden tools never actually invoked, NOT_VERIFIED-style honesty where expected, and a full before/after snapshot of every mutable Assync record proving no mutation occurred across the whole run) -- never exact prose matching, since real model phrasing varies run to run. Response clarity is printed for human review, not auto-graded.