Repository navigation
Promptise Foundry 1.10.0
Security fixes for custom MCP auth providers, approval gates and inbox scanning, a deadline for streamed runs, and fixes found while checking every guide against 1.9.0.
Upgrade notes
- A
.envis looked for only up to the project root: the nearest folder withpromptise.toml,pyproject.tomlor.git, or the working directory when there is none. A project nested in another repository no longer loads that repository's.env; list a shared file on purpose with[env] files = ["../.env"]. astream()andastream_with_tools()can raiseTimeoutErroron an agent withmax_invocation_time. Before, streams had no deadline. Forastream_with_tools()this is a raised exception, not anErrorEvent.- A
TimeoutErrorraised inside a run is reported as itself.ainvoke()(andchat(),invoke()) gave "Agent invocation exceeded Ns timeout" for aTimeoutErrorfrom an input guardrail, memory or another step outside the graph; code that caught that message for such failures now gets the original error. - A
ValidateNode(or another reasoning node) that ends the run leaves the answer asmessages[-1]. Its JSON verdict was appended after the answer it checked; the verdict is instate.context[output_key]("validation"for aValidateNode). - Servers with a custom auth provider and
require_auth=Truewarn at startup on HTTP and SSE when the provider has noaverify_token(): bad credentials are then refused per call, not with a 401 at connect. Addaverify_token()to refuse them at the transport.
Security
- A custom MCP auth provider that refused by returning a value let the call through --
AuthMiddlewareused whateverauthenticate()returned, soNone,Falseor""reached the tool as the client ID. It now refusesNone, any bool and empty strings withAUTHENTICATION_ERRORand logs a warning naming the provider. - The MCP approval gate let a call through when the handler raised
TimeoutErrorunderon_timeout="allow"-- on Python 3.11+asyncio.TimeoutErrorisTimeoutError, so a handler's own error looked like the gate's timeout. Approval gates (agent and MCP server) andElicitor.asknow tell the two apart: a handler error fails closed ("Approval handler error: TimeoutError") and is not a reviewer denial formax_retries_after_deny. - Inbox messages ignored
redact_input=True-- the scanner produced redacted text, but the inbox stored the raw message. Inbox messages now follow the scanner's input policy: withredact_input=Truea credential or PII is stored redacted, a BLOCK finding still refuses the message, and with the default a message carrying a credential is accepted and logs one warning with the finding categories, never the value. - A long credential across a scan-window boundary was missed -- inbox messages and trigger payloads were scanned in 500-character windows that overlapped by 50, so a long API key split across two windows was neither redacted nor blocked. Both are now scanned whole; scanners that don't window their models themselves still get the 500-character windows as well.
Fixed
AuditMiddleware(include_args=True)wrote"args": {}for a call that failed argument validation -- it now records the arguments the caller sent, withstatus: "error"andVALIDATION_ERROR. Long strings and large lists in rejected input are clipped and marked.StructuredLoggingMiddleware(include_args=True)does the same, after its usual redaction.- An approval-denied call's
tool.calltrace entry had no status -- it now carriesstatus="denied",denied_by="approval"and thereason, like itstool.resultand like a budget-refused call. max_invocation_timedid not apply toastream()andastream_with_tools()-- the deadline now covers the whole stream, the time the consumer spends between events included. When it passes, the stream stops (its cleanup still runs),TimeoutError("Agent invocation exceeded Ns timeout")is raised andinvocation.timeoutis emitted withstreaming: true. Stopping a stream early is not a timeout, and now runs the stream's cleanup at once.- "Future exception was never retrieved: InboxQuestionRemoved" -- clearing the inbox, or a question expiring, being evicted or removed by a later scan, no longer logs it when the
/askwaiting for the question had already timed out. - The first sandbox session hung silently for minutes while Docker pulled the image -- the pull was logged at INFO, which default logging hides, and it blocked the event loop. It now runs in a worker thread and logs a warning when it starts, a progress line every 10 seconds and when it ends; a failed pull raises with Docker's error, and a daemon error is no longer taken for a missing image.
- Memory search reported a provider's own
TimeoutErroras the search timeout -- it is now logged as a failed search with the provider's error; onlymemory_timeoutpassing gives "timed out after Ns".
Docs
- The event reference lists every process event (
process.restart_exhausted,process.suspended,process.resumed,process.rewound) with its payload, andinvocation.timeoutwithtimeout_secondsandstreaming. astream()andastream_with_tools()record tool failures and inject lessons, likeainvoke(); the adaptive strategy page said they didn't.ToolEndEvent.reusedis also set for repeats deduplicated byToolNode(deduplicate=True).- The MCP server auth page documents the custom provider contract (raise
AuthenticationErrorto refuse) and refusing at the transport withaverify_token(). - Context compaction: set
max_result_charswhen tools return whole files, since each re-read adds a full copy. CredentialDetectorhas 97 patterns (some posts said 96); table cells that lost their dash shownoneor their value; links to renamed guides use the current titles.
Full changelog: https://docs.promptise.com/resources/changelog/