Model or dataset
undertheseanlp/underthesea avatar
undertheseanlp/underthesea

Underthesea v9.5.0: A Vietnamese NLP Library That Now Ships an Agent Runtime

Underthesea - AI Assistant

1,808 stars307 forksPythonApache-2.0

At a glance

What is it?
Underthesea began as a Vietnamese NLP toolkit and, since v9.3.0, also ships an agent runtime built on Python's standard library. The agent layer is the interesting part and also the part with the most caveats.
Who is it for?
Adopt Underthesea if you are building Vietnamese-language NLP pipelines and want an agent loop that adds no SDK dependency, or if you need an A2A endpoint in front of an existing agent and want to avoid pulling in a web framework. Do not adopt it as a general-purpose agent framework for non-Vietnamese work, and do not assume the bundled default tools are safe to expose without reading their implementations first.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

Vietnamese NLP Is Still the Reason to Install It, Not the Agent

The repository's own topic list puts vietnamese and word-segmenter alongside agentic-ai and llm. That ordering is honest. Underthesea's original identity is Vietnamese natural language processing, and the README still points at the Vietnamese NLP documentation as the core of the project. The agent toolkit arrived later, at v9.3.0, according to the README's own version note. So the practical question for most readers is not whether Underthesea can run an agent loop. It is whether the Vietnamese NLP modules plus a bundled agent loop beat installing a Vietnamese NLP library and a separate agent framework and wiring them together. The answer depends on how much you value having one dependency instead of two, and on whether the agent's feature set covers what you need. It is a narrower toolkit than a dedicated agent framework, and the README does not claim otherwise.

The Agent Makes HTTP Calls With urllib and json, Nothing Else

The most concrete design decision in the README is the dependency constraint. The agent communicates with LLM APIs using only Python's standard library, specifically urllib plus json, and the README states that no openai, anthropic, or google-genai package is required. Four providers are supported: OpenAI, Azure OpenAI, Anthropic Claude, and Google Gemini. Each is exposed as its own class, and the README says this follows the Anthropic SDK pattern. There is also an LLM() class that auto-detects the provider from environment variables. The consequence cuts both ways. You get a very small install footprint and no version conflicts between provider SDKs, which matters in environments where pinning dependencies is painful. You also get no benefit from whatever those SDKs do beyond the request layer: retries with backoff, connection pooling, typed response objects, or provider-specific features added after this code was written. If your application depends on a provider feature that only exists in the official SDK, this design will not expose it unless Underthesea adds it by hand. The README does not describe a retry policy, so treat that as unverified.

Tool Calling, Default Tools, and Where the Trust Boundary Sits

Tools are declared by wrapping a Python function in a Tool object and passing a list to the Agent constructor. The README's weather example shows the docstring becoming the tool description, which is the convention most function-calling APIs use. Separately, the package ships default_tools, described as 12 built-in tools covering calculator, datetime, web search, wikipedia, file I/O, shell, and python exec. That list deserves attention. A shell tool and a python exec tool, handed to a model that decides when to call them, are a code execution surface. The README presents them as a convenience and gives no sandboxing, permission model, or allowlist in the material provided. Whether they are safe depends entirely on the implementation, which is not in the README. For a local prototype this is fine. For anything reachable by untrusted input, importing default_tools wholesale is the wrong move, and you would want to pass only the specific Tool wrappers you have reviewed. The README also mentions calculator_tool and Tool(add) as individual tools, which is the pattern to follow when you want a narrow surface.

Tracing Is On by Default and Writes to Your Home Directory

Every agent call is traced automatically to ~/.underthesea/traces/, and the README says this can be disabled with the environment variable UNDERTHESEA_TRACE_DISABLED=1. The trace output shown in the README includes a trace ID, per-step timing, model name, and token counts in the form 100->18 tokens, with each trace written as a timestamped JSON file. Langfuse is supported as an alternative tracer via LangfuseTracer(), which requires installing langfuse separately, and there is a @trace decorator that turns nested functions into child spans while inheriting the surrounding trace context. The default-on behaviour is a deliberate choice and a debatable one. It is convenient for debugging, and it means traces exist whether or not you remembered to configure anything. It also means prompt and completion content may be landing on disk in a predictable location on every machine that runs your code, including CI containers and developer laptops. The README does not state what fields are serialized or whether content is redacted. If your prompts contain user data, verify the file contents before shipping, or set the disable variable in the environments where you do not want them.

Serving an Agent Over A2A Without a Web Framework

Version 9.5.0 is labelled A2A Agent Server in the release list. The serve() function takes an agent, a port, a path, and a ui flag, and the README shows three resulting endpoints: a bundled chat UI at the path plus /ui, an agent card at /.well-known/agent-card.json, and a JSON-RPC endpoint at the path itself that uses message/stream over HTTP with server-sent events. The server is described as a raw ASGI app with no web-framework dependency in the base install, and make_app() returns that ASGI callable so you can mount it in uvicorn or hypercorn yourself. There is an optional extra, pip install 'underthesea[agent-server]', which pulls in uvicorn, starlette, and httpx for convenience. Two things are worth flagging. First, the README links the A2A protocol to the google-agentic-commerce/AP2 repository, which is a different specification from A2A as generally documented; if protocol conformance matters to you, check which one the implementation actually follows. Second, a raw ASGI app means you own authentication, TLS termination, rate limiting, and request size limits. Nothing in the README suggests any of that is built in, and an unauthenticated JSON-RPC endpoint that can invoke a shell tool is a serious combination.

Multi-Session Handoff and What the README Leaves Unstated

The Session class is aimed at long-running agents. The README's researcher example creates a Session with a progress_file of progress.json, calls create_task with a description and a list of steps, then calls run_until_complete with max_sessions=5. The README attributes the pattern to Anthropic's writing on harnesses for long-running agents. The mechanism, as far as the material shows, is that the agent works until it hits a session boundary, writes progress to the named file, and a later session resumes from that state. That is a reasonable approach to context limits, and the progress file is plain JSON you can inspect. What the README does not describe is how a session decides it is done, what happens if the process dies mid-write, or whether progress.json is written atomically. Those are the questions that determine whether this survives a crash, and the material does not answer them. If you plan to run unattended agents on this, read the Session implementation before trusting the resume path.

Licence, Maintenance, and the Cost of an Agent Framework You Own

Underthesea is Apache-2.0, which permits commercial use and modification and includes an explicit patent grant, with the usual requirements around preserving notices and stating changes. That is a permissive licence and, for most adopters, the least complicated part of this decision. The maintenance picture is the part to think about. The release cadence visible in the supplied material is roughly monthly across v9.3.0, v9.4.0, and v9.5.0, with the last push in September 2026. The agent API is young: it appeared at v9.3.0, tracing at v9.4.0, and the A2A server at v9.5.0. Three releases in, the surface is still moving, and the README's own examples are the primary specification. That means upgrades may change constructor arguments or tool interfaces, and your integration tests are the thing that catches it. The offsetting cost is low: because the agent has no third-party SDK dependencies, there is no dependency tree to reconcile at upgrade time. The real maintenance burden is reading the source to answer the questions the README does not, which is a one-time cost per feature you rely on, not a recurring one. This is not legal advice; check the Apache-2.0 text and your own counsel for your situation.

When to Reach for Something Else

A general-purpose agent framework such as LangChain or LlamaIndex is the alternative most readers will weigh, and the difference is not feature count. Those projects target breadth: many integrations, many retrieval strategies, many vector stores, and provider SDKs underneath so you inherit their retry and streaming handling. Underthesea targets a narrow slice and pays for it with a hand-written HTTP layer and a fixed set of four providers. If your work is Vietnamese text processing and you want an agent loop in the same package, the narrowness is a feature. If your work is a multi-step agent over a vector store with a dozen integrations, Underthesea is the wrong tool and you will spend your time reimplementing what the broader frameworks already ship. The honest framing is that Underthesea's agent is a convenience for people already using Underthesea, not a competitor to a full agent platform. The README does not present it as one, and reading it as one leads to disappointment.

Editorial conclusion

Adopt Underthesea if you are building Vietnamese-language NLP pipelines and want an agent loop that adds no SDK dependency, or if you need an A2A endpoint in front of an existing agent and want to avoid pulling in a web framework. Do not adopt it as a general-purpose agent framework for non-Vietnamese work, and do not assume the bundled default tools are safe to expose without reading their implementations first. Before committing, verify three things against the actual source: what each of the 12 default tools does, whether the trace files written to ~/.underthesea/traces/ are acceptable under your data-handling rules, and whether the A2A endpoint described in the README matches the AP2 repository it links to, since the two are not the same specification.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. undertheseanlp/underthesea on GitHub
Community notes

Community notes