pub struct AgentCat { /* private fields */ }Expand description
A handle to AgentCat for one project. Clones are cheap and share everything, so one handle
serves every server instance: a streamable HTTP service builds one handler per session or per
request, and each of them is wrapped with AgentCat::track.
use agentcat_sdk::{AgentCat, Options};
let agentcat = AgentCat::new("proj_123", Options::default());
let make_server = {
let agentcat = agentcat.clone();
move || agentcat.track(MyServer)
};Its Debug output shows the project ID and the options only.
§Dropping the last handle
A handle delivers its events from its own thread, which the first event or log line starts.
When the last clone drops (the Tracked servers hold clones too) while that thread runs,
the drop runs shutdown with a 5 s timeout and blocks the dropping thread
until the delivery thread answers: at most about 5 s, less when the events finish sooner. The
events that have not finished at the deadline are dropped.
The hooks of Options (resolve_session_id, identify, event_tags, event_properties,
redact_sensitive_information and redact_event) run on the tokio runtime of the tool call.
On a current-thread runtime, such as #[tokio::main(flavor = "current_thread")], a drop on
the runtime’s thread blocks its only thread, so no hook can run during the wait: an event that
still needs a hook waits for the whole 5 s and is then dropped. Call shutdown(timeout).await
before the runtime ends, while the hooks can still run:
use std::time::Duration;
// ... serve until the client goes away ...
let delivered = agentcat.shutdown(Duration::from_secs(5)).await;A hook of Options that holds a clone of the handle makes a reference cycle: the handle
holds its options, and the options hold the hook. The handle then never drops, so the drain
of the last drop never runs. Call shutdown before the process ends, or let
the hook capture only what it needs. A tool reaches the handle through
CallContext::agentcat, so it needs no clone.
A drop on the delivery thread itself does not wait. A handle whose delivery thread never
started has nothing to drain. The drain does not run at all after std::process::exit or a
panic under panic = "abort".
Implementations§
Source§impl AgentCat
impl AgentCat
Sourcepub fn new(project_id: impl Into<String>, options: Options) -> Self
pub fn new(project_id: impl Into<String>, options: Options) -> Self
A handle for project_id. Building one cannot fail and starts no thread until the first
event or log line. An empty project_id means telemetry only: events are built but never
sent to AgentCat.
The environment variable AGENTCAT_ENABLED set to false, 0,
no or off (any case, surrounding white space ignored) turns the handle off: it never
starts a thread, its Tracked servers forward every method to the wrapped handler
untouched (a tool still gets its CallContext, with no session and
no agent), custom events return Ok(()) at once and publish nothing (also for an empty
project ID), and the lifecycle methods return true. The same holds for track and
AgentCat::from_env.
Sourcepub fn from_env(options: Options) -> Self
pub fn from_env(options: Options) -> Self
A handle like AgentCat::new for the project that the environment variable
AGENTCAT_PROJECT_ID names. When it is unset or empty, the handle is telemetry only, as
AgentCat::new with an empty project ID.
use agentcat_sdk::{AgentCat, Options};
// AGENTCAT_PROJECT_ID=proj_123 in the environment.
let agentcat = AgentCat::from_env(Options::default());Sourcepub fn track<H: ServerHandler>(&self, handler: H) -> Tracked<H>
pub fn track<H: ServerHandler>(&self, handler: H) -> Tracked<H>
Wraps handler so that this handle sees its tool listings and tool calls. Cheap: it
clones the handle and does no other work.
Sourcepub fn publish_custom_event(
&self,
session_id: &str,
project_id: &str,
event: CustomEvent,
) -> Result<(), Error>
pub fn publish_custom_event( &self, session_id: &str, project_id: &str, event: CustomEvent, ) -> Result<(), Error>
Publishes a custom event to the project project_id for the session session_id. It only
queues the event, so it returns at once.
The session is the event’s own session_id when it is not
empty, else session_id verbatim (it may be empty for none). The event has no server or
client fields and goes through no redaction hook. It is queued even while tracing is off.
A handle that AGENTCAT_ENABLED turned off returns Ok(()) at once and publishes nothing.
use agentcat_sdk::{AgentCat, CustomEvent, Options};
let agentcat = AgentCat::new("proj_123", Options::default());
let event = CustomEvent::new().resource_name("cache-warmed").message("40 keys");
agentcat.publish_custom_event("ses_1", "proj_123", event)?;§Errors
Error::ProjectIdRequired when project_id is empty, except on a handle that
AGENTCAT_ENABLED turned off, which returns Ok(()) and does nothing.
Sourcepub async fn flush(&self, timeout: Duration) -> bool
pub async fn flush(&self, timeout: Duration) -> bool
Waits until every event this handle took so far is delivered, for at most timeout;
true when that happened in time. Events taken while it waits are waited for too.
The SDK’s delivery thread keeps the time, so the calling runtime needs no timer. Events
still go out after a false. Use it before a short-lived process ends, or in a test.
It returns true at once when the handle has taken no event yet, and after a
shutdown has ended, also one that timed out: nothing is left to
deliver. Once polled, the wait stays with the delivery thread until the events are
delivered or timeout passes, also when the future is dropped first (for example by a
timeout).
use std::time::Duration;
let delivered = agentcat.flush(Duration::from_secs(5)).await;Sourcepub async fn shutdown(&self, timeout: Duration) -> bool
pub async fn shutdown(&self, timeout: Duration) -> bool
Like flush, then stops this handle for good: every event it takes from
the call on is dropped, for all its clones. When timeout passes first, the events left
are abandoned and it returns false.
Once polled, the shutdown runs to its end, also when the future is dropped first (for
example by a timeout): the handle drops later events and stops once its events are
delivered or timeout passes. A second shutdown after the first has ended returns
true at once.
Without it, the drop of the last clone runs the same shutdown with a 5 s timeout and
blocks the dropping thread while it runs: see dropping the last
handle. std::process::exit and a panic under
panic = "abort" skip that drain.
Sourcepub fn flush_blocking(&self, timeout: Duration) -> bool
pub fn flush_blocking(&self, timeout: Duration) -> bool
flush that blocks the calling thread for at most timeout (and a few
milliseconds more). It needs no tokio runtime; on a runtime thread it blocks that thread.
Sourcepub fn shutdown_blocking(&self, timeout: Duration) -> bool
pub fn shutdown_blocking(&self, timeout: Duration) -> bool
shutdown that blocks the calling thread for at most timeout (and a
few milliseconds more). It needs no tokio runtime; on a runtime thread it blocks that
thread.