
Product
A Fresh Look for the Socket Dashboard
We’ve redesigned the Socket dashboard with simpler navigation, less visual clutter, and a cleaner UI that highlights what really matters.
A Python library that simplifies building AI-driven chatbots with OpenAI, offering conversation management, file attachments, and persistent storage in one cohesive package.
ChatWeaver is a Python library designed to simplify and enhance chatbot development with OpenAI. By offering intuitive abstractions and structures—such as the Model
, Bot
, Chat
, TextNode
, and CWArchive
classes—ChatWeaver consolidates much of the boilerplate and complexity associated with multi-turn conversations, file integrations, and persistent storage.
Chat
sessions or multiple objects with CWArchive
.Model
A wrapper for OpenAI-based models, ensuring valid API keys and model names.
Initialization:
from chatweaver import Model
# Provide an API key and optionally specify the model name
model = Model(api_key="sk-1234567890abcdef1234...", model="gpt-4o")
Key Capabilities:
Bot
Extends Model
to create a customizable AI assistant with definable rules and a unique name.
Initialization:
from chatweaver import Bot
bot = Bot(
api_key="sk-1234567890abcdef1234...",
rules="You are a helpful assistant that responds concisely.",
name="ConciseBot"
)
Key Capabilities:
response(...)
method to generate replies to user prompts, including support for file attachments.TextNode
A lightweight, immutable container for individual messages in a conversation.
Example:
from chatweaver import TextNode
# Represents a user's message
user_node = TextNode(
role="user",
content="Hello, what's the weather like?",
owner="Alice",
tokens=8,
date="2025-01-01 09:15:00"
)
Key Capabilities:
Chat
Builds upon the Bot
to manage an entire conversation session, storing user/assistant exchanges (TextNode
objects), reply limits, and session-level metadata like title or creation date.
Initialization:
from chatweaver import Chat
# Pass an existing Bot or let Chat create its own under the hood
chat_session = Chat(
api_key="sk-1234567890abcdef1234...",
title="Support Session",
replies_limit=5,
user="Customer"
)
Key Capabilities:
chat_history
.chat_replies_limit
).get_response(...)
to seamlessly generate and store new user and assistant messages:
user_input = "Hi! I need help with my order."
assistant_reply = chat_session.get_response(prompt=user_input)
print("Assistant:", assistant_reply)
Useful Properties:
chat_replies
– counts how many user+assistant pairs have occurred.chat_cost
– sums the tokens used across all messages.chat_title
– a helpful descriptor for logs or archives.CWArchive
Handles persistent storage of any combination of Chat
, Bot
, or Model
objects. You can load, save, and manage them by their integer IDs or by direct reference to the objects.
Initialization:
from chatweaver import CWArchive
archive = CWArchive(
path="my_chats.archive"
)
Key Capabilities:
Usage:
# Suppose we have a Chat object we want to store
chat_session = Chat(api_key="sk-1234567890abcdef1234...", title="My Chat Session")
# Add the chat to the archive
archive.add(chat_session)
# Save changes to disk
archive.save()
# Retrieve all objects (may load asynchronously in parallel)
data = archive.archive_data
for item_id, chat_obj in data.items():
print(item_id, chat_obj)
# Remove an item (by ID or by reference)
archive.remove(0) # remove the object with ID = 0
# or
archive.remove(chat_session)
Below is a high-level example illustrating how you might use ChatWeaver end-to-end:
from chatweaver import Model, Bot, Chat, CWArchive
# 1. Create a Model
model = Model(api_key="sk-1234567890abcdef1234", model="gpt-4o")
# 2. Create a Bot with custom rules, tied to the Model
rules = "You are a friendly and knowledgeable assistant."
bot = Bot(
cw_model=model,
rules=rules,
name="HelpfulBot"
)
# 3. Start a Chat session using the Bot
chat = Chat(
cw_bot=bot,
title="Demo Session",
replies_limit=3, # limit to 3 user+assistant replies
user="Tester"
)
# 4. Interact with the Chat
response1 = chat.get_response("Hello, how are you?")
print("Bot:", response1)
response2 = chat.get_response("Can you tell me a joke?")
print("Bot:", response2)
# Check Chat details
print("Current replies used:", chat.chat_replies)
print("Total tokens so far:", chat.chat_cost)
# 5. Save the Chat to an Archive
archive = CWArchive(path="demo_archive.txt", asynchronous=True, delay=0.07)
archive.add(chat)
archive.save()
# 6. Retrieve data from the archive and display
loaded_data = archive.archive_data
for item_id, obj in loaded_data.items():
print(f"Item ID {item_id} -> {obj}")
In this script:
Model
.Bot
. We optionally limit how many user+assistant pairs are allowed.Chat
to an archive file and later re-load it to continue the session.ChatWeaver aims to reduce the friction in creating robust, multi-turn chatbot experiences powered by OpenAI. Whether you need to store your sessions locally, manage advanced conversation rules, or simply test a new idea in minutes, ChatWeaver’s structured approach and flexible design provide a powerful toolkit for modern chatbot development.
The Model class provides a straightforward way to configure and manage OpenAI-based API clients. It validates and stores both the model name and the API key, automatically initializing a matching OpenAI client for you.
model_api_key: str
Retrieve or set the API key associated with this Model. Must begin with "sk-"
and be at least 20 characters long.
model_model: str
Retrieve or set the model name. The default value is "gpt-4o"
. Changing this property triggers internal validation against an accepted list of models.
model_client: openai.OpenAI
Retrieve the current OpenAI client. When the API key changes, a new client is automatically created.
Below is an overview of the principal methods available on the Model class.
Constructor
__init__(api_key: str, model: str = "gpt-4o")
Initializes the Model with a valid API key and an optional model name.
api_key (str)
: Must begin with "sk-"
and be at least 20 characters.model (str)
: The model name to use, defaulting to "gpt-4o"
.Exception
: If either the model name or the API key fails validation.__str__() -> str
Returns a user-friendly string containing the current model name and a partially obfuscated API key.
__repr__() -> str
Returns a more detailed string representation useful for debugging or logging.
__eq__(other) -> bool
Determines equality between two Model instances by comparing both their model names and API keys.
model_model (getter)
Retrieves the currently set model name.
model_model (setter)
Validates and sets a new model name. Raises an Exception
if the new name is not in the accepted list of models.
model_api_key (getter)
Retrieves the currently stored API key.
model_api_key (setter)
Validates the format of the new API key (must start with "sk-"
and be at least 20 characters). Performs a test request to ensure the key is valid. If successful, updates the API key and re-initializes the client.
model_client (getter)
Retrieves the OpenAI client currently in use.
model_client (setter)
Explicitly sets a new OpenAI client by providing the same API key already stored in model_api_key
. If the provided key does not match the stored one, an exception is raised.
from chatweaver import Model
# Initialize the Model with a valid API key and optionally specify the model name
model_instance = Model(api_key="sk-1234567890abcdef1234", model="gpt-4o")
# Check basic info
print(str(model_instance))
# Example Output: <Model | model=gpt-4o, api_key=sk-1234567...4564>
# Update the model name (must be in the allowed set of models)
model_instance.model_model = "gpt-4o"
# Update the API key (re-initializes the OpenAI client if validation succeeds)
model_instance.model_api_key = "sk-0987654321abcdef5678"
# Retrieve the OpenAI client to make requests manually (if needed)
client = model_instance.model_client
# Compare with another Model instance
another_model = Model(api_key="sk-0987654321abcdef5678", model="gpt-4o")
print(model_instance == another_model) # True, if both model name and API key match
Use the Model class to simplify how you manage different OpenAI models and keys across your chatbot applications.
The Bot class extends the capabilities of the Model
class to create a conversational AI entity. It allows you to specify custom rules, assign a name to the bot, and configure time formats. You can also use it to generate responses to user queries, optionally integrating images or file uploads.
Model
.Model
instance, you can pass it in; otherwise, the Bot
will initialize its own Model
by inheriting from Model
.bot_rules: str
The conversation rules that guide the bot’s responses. These rules can be overridden if needed. The getter automatically appends the bot’s name to provide context in dialogues.
bot_name: str
The human-readable name assigned to the bot (default is "AI Bot"
). This name also appears in the conversation rules.
bot_time_format: str
The format string used for handling timestamps in the bot’s operation (default is "%d/%m/%Y %H:%M:%S"
).
bot_Model: Model
The underlying Model
instance that interfaces with OpenAI. Access this property when you need direct control over the model settings or the OpenAI client.
Below is a summary of the key methods in the Bot class.
__init__( *args, rules: str | None = ..., name: str = "AI Bot", cw_model: Model | None = None, **kwargs ) -> None
Initializes the Bot with optional rules, a custom name, and an existing Model
(if available). If no Model
is provided, the bot internally creates one by calling super().__init__
.
Parameters:
*args
: Additional positional arguments passed to the parent Model
if cw_model
is not given.rules (str | None)
: Conversation rules for the bot. Falls back to default if None
.name (str)
: The bot’s name (default is "AI Bot"
).cw_model (Model | None)
: An existing Model
instance. If None
, a new Model
is created.**kwargs
: Additional keyword arguments passed to the parent Model
if cw_model
is not given.Raises:
TypeError
: If cw_model
is provided but is not a Model
instance.__str__() -> str
Returns a friendly string with the bot’s name, for quick identification.
__repr__() -> str
Returns a more detailed string representation, useful for debugging (includes name, rules, and the underlying Model
).
__eq__(other: Bot) -> bool
Compares this bot to another Bot instance. Returns True
if both have the same rules, name, and underlying Model
.
bot_Model (getter)
Retrieves the underlying Model
used by this bot. This allows you to work directly with the Model
’s methods and properties if needed.
bot_rules (getter/setter)
None
, defaults to a predefined rule set.bot_name (getter/setter)
bot_time_format (getter/setter)
ValueError
if the format is invalid.Use the response
method to get a chatbot response from a user prompt:
response(prompt: str, user: str = "User", history: list | None = None, image_path: str | None = None, file_path: str | None = None) -> dict[str, Any]
Constructs a message set (including optional conversation history) and sends it to the underlying Model
’s OpenAI client. If image_path
or file_path
is provided, these files are appropriately handled (e.g., base64-encoded images, file uploads) and referenced in the prompt.
Parameters:
prompt (str)
: The user’s query or statement.user (str)
: A label for the user in conversation (default is "User"
).history (list | None)
: Optional prior messages to maintain context.image_path (str | None)
: Local path to an image to be included.file_path (str | None)
: Local path to any file to upload and reference.Returns (dict[str, Any]
):
"content"
: The text generated by the model."prompt_tokens"
, "completion_tokens"
, "total_tokens"
: Token usage statistics."start_date"
: Timestamp at which the request started."final_date"
: Timestamp at which the request finished."delta_time"
: Elapsed time for the model to produce the response.from chatweaver import Bot, Model
# 1. Using an existing Model
existing_model = Model(api_key="sk-1234567890abcdef1234...", model="gpt-4o")
bot = Bot(
cw_model=existing_model,
rules="You are a helpful assistant with a witty sense of humor.",
name="FriendlyBot"
)
# 2. Or let Bot create a new Model internally
another_bot = Bot(
api_key="sk-0987654321abcdef5678...", # Passed to Model's constructor
rules="You are a formal assistant that provides concise answers.",
name="ConciseBot"
)
# 3. Generating a response to a user prompt
response_data = bot.response(
prompt="What is the capital of France?",
user="Alice",
image_path=None,
file_path=None
)
# Check response
print("Bot response:", response_data["content"])
print("Token usage:", response_data["total_tokens"])
In this example, you can see how you might create Bot
instances—either using an existing Model
or letting Bot
handle model creation. You can then generate answers to user prompts, optionally providing conversation history and file attachments.
The TextNode class is a simple, immutable data container representing a single message in a conversation. Each instance stores key information about the message, including its role (assistant or user), the message content, the name of the owner, token usage, and creation date.
TextNode
is defined with @dataclass(frozen=True)
, meaning its fields cannot be modified after creation.TextNode
encapsulates one message. In a broader chatbot flow, multiple TextNode
instances together form the conversation history.role: str
The role associated with this text node, typically "assistant"
or "user"
.
content: str
The actual text content of the message.
owner: str
The name or identifier of the owner of this node (e.g., "AI Bot"
, "User"
, etc.).
tokens: int
The number of tokens estimated or measured for this message content. Useful for tracking token usage in OpenAI-based systems.
date: str
A string representation of the date or timestamp at which this message was created.
__str__() -> str
Returns a JSON-like string of all attributes in the TextNode
. For example:
{
"role": "assistant",
"content": "Hello!",
"owner": "AI Bot",
"tokens": 5,
"date": "2024-12-31 10:00:00"
}
__iter__() -> dict
Provides an iterator over the TextNode
’s attributes as key-value pairs. This allows you to quickly convert a TextNode
to a dictionary by calling dict(text_node_instance)
.
Below is a simple demonstration of how you might create a TextNode
and then inspect its attributes.
from chatweaver import TextNode
# Create a TextNode representing a user's message
user_message = TextNode(
role="user",
content="What's the weather like today?",
owner="Alice",
tokens=8,
date="2025-01-01 09:15:00"
)
# Print the node in a JSON-like string representation
print(str(user_message))
# Output:
# {
# 'role': 'user',
# 'content': "What's the weather like today?",
# 'owner': 'Alice',
# 'tokens': 8,
# 'date': '2025-01-01 09:15:00'
# }
# Convert the TextNode to a dictionary for further processing
node_dict = dict(user_message)
print(node_dict["content"]) # "What's the weather like today?"
Use TextNode
objects to store and pass around conversation messages reliably, ensuring their metadata remains intact across different parts of your chatbot or application.
The Chat class extends the functionality of the Bot
class to manage a full conversation session. It retains a history of messages (via TextNode
objects), handles reply limits, and tracks metadata such as the chat title, creation date, and total cost (in tokens). This class is ideal for organizing multi-turn conversations in applications or services that require persistent context.
TextNode
s.Bot
(and thus with a Model
) to generate responses.chat_time_format: str
The string format used for timestamps (by default "%d/%m/%Y %H:%M:%S"
).
chat_replies_limit: int
The maximum number of user+assistant reply pairs allowed in the session. If set to None
, there is no limit.
chat_history: list[TextNode]
A list of TextNode
instances, each representing a message (user or assistant) in the conversation.
chat_user: str
The identifier for the user participating in the chat (e.g., "User"
, "Alice"
, etc.).
chat_creation_date: str
A timestamp indicating when the chat session was created, using chat_time_format
.
chat_replies: int
The current number of user+assistant message pairs in the conversation (computed from chat_history
).
chat_cost: int
The sum of all tokens used across the conversation. Calculated by summing the tokens
attribute of each TextNode
.
chat_title: str
A descriptive title for the chat session (e.g., "New Chat"
, "Customer Support Session"
, etc.).
__init__(*args, title="New Chat", replies_limit=10, user="User", cw_bot=None, **kwargs)
Creates a new chat session with an optional title, reply limit, user identifier, and existing Bot
. If no Bot
is provided, the constructor creates one internally (inheriting from Bot
).
Parameters:
*args
: Positional arguments passed to the underlying Bot
or Model
constructor, if cw_bot
is not provided.title (str)
: The chat title ("New Chat"
by default).replies_limit (int | None)
: The maximum number of user+assistant pairs. None
means no limit (defaults to 10
).user (str)
: Name or identifier of the user ("User"
by default).cw_bot (Bot | None)
: An existing Bot
. If None
, a new one is created.**kwargs
: Additional keyword arguments passed to the Bot
or Model
constructor if cw_bot
is not provided.Raises:
TypeError
: If cw_bot
is provided but is not a Bot
instance.__str__() -> str
Returns a concise string representation, including the chat title, reply limit, current reply count, and creation date.
__repr__() -> str
Returns a detailed string for debugging or logging, including attributes such as the reply limit, user, title, and the associated Bot
.
__lt__(other: Chat) -> bool
Enables chronological sorting by comparing chat_creation_date
between two Chat
instances.
__eq__(other: Chat) -> bool
Checks if two Chat
objects have the same essential attributes: reply limit, user, title, creation date, number of replies, history, and the same underlying Bot
.
chat_Bot (getter)
Retrieves the underlying Bot
instance. Useful if you need direct access to its rules or the Model
it uses.
chat_time_format (getter/setter)
ValueError
if invalid.chat_replies_limit (getter/setter)
float('inf')
if no limit).None
(treated as infinite). Raises a TypeError
if the value cannot be converted to int
.chat_history (getter/setter)
TextNode
messages.TextNode
s or a list of dictionaries convertible to TextNode
. Raises a TypeError
for invalid data.chat_user (getter/setter)
str
.chat_creation_date (getter/setter)
str
formatted according to chat_time_format
.ValueError
if incorrect.chat_replies (getter)
Calculates the number of user+assistant pairs from the chat_history
. Each pair corresponds to two messages (one user and one assistant).
chat_cost (getter)
Sums the tokens
attribute of each TextNode
in chat_history
to provide a cumulative token usage.
chat_title (getter/setter)
str
.set_all(return_self: bool = True, **kwargs: Any) -> Chat | None
Dynamically updates multiple attributes on the Chat
(and on its underlying Bot
or Model
) using keyword arguments.
"_Chat__user"
, "_Bot__rules"
, "_Model__api_key"
).Chat
instance itself if return_self
is True
, otherwise None
.Use get_response
to interact with the chat:
get_response(prompt: str, user: str | None = None, image_path: str | None = None, file_path: str | None = None) -> str
Generates an assistant’s response to the given prompt
, optionally attaching an image or file. The new user and assistant messages are appended to chat_history
as TextNode
objects.
Parameters:
prompt (str)
: The user’s text input.user (str | None)
: Custom user identifier for this prompt. Defaults to chat_user
if None
.image_path (str | None)
: Path to an image file to include in the request.file_path (str | None)
: Path to a file to upload for reference.Returns:
str
containing the assistant’s response content.from chatweaver import Chat, Bot, TextNode
# 1. Creating a Chat with a custom Bot
my_bot = Bot(api_key="sk-1234567890abcdef1234...", rules="You are a friendly assistant.")
my_chat = Chat(
cw_bot=my_bot,
title="My AI Discussion",
replies_limit=5,
user="Alice"
)
# 2. Getting a response
assistant_reply = my_chat.get_response("Hello, can you tell me a joke?")
print("Assistant says:", assistant_reply)
# 3. Accessing chat history
for node in my_chat.chat_history:
print(node.role, node.content, sep=": ")
# 4. Viewing total token usage
print("Total token usage:", my_chat.chat_cost)
# 5. Changing chat title
my_chat.chat_title = "Jokes and More"
# 6. Setting multiple attributes at once
my_chat.set_all(
_Chat__replies_limit=None, # No longer limit the replies
_Bot__rules="Stay professional in your answers."
)
print("Updated chat limit:", my_chat.chat_replies_limit)
print("Updated bot rules:", my_chat.chat_Bot.bot_rules)
In this example, you create a Chat
using a specific Bot
, ask for a response, and then manipulate or inspect the Chat
’s properties. The session automatically tracks message history (via TextNode
objects), token usage, and enforces reply limits (if specified).
The CWArchive class provides a convenient way to store and manage Chat
, Bot
, or Model
objects in a single file. It supports both synchronous and asynchronous loading, as well as basic add, remove, and retrieval operations. This makes it suitable for saving and restoring chatbot sessions, bots, or model configurations in a controlled, persistent manner.
Chat
, Bot
, and Model
objects with minimal setup.__enter__
and __exit__
methods handle setup and teardown logic, ensuring that save() is automatically called on exit.archive_path: str
The filesystem path where the archive is stored.
archive_data: dict
A dictionary of stored objects, keyed by integer IDs.
archive_id: int
The next available integer ID that can be used when adding a new item.
archive_delay: float
The delay (in seconds) between asynchronous load operations. Adjust this if you experience race conditions in multi-threaded contexts.
archive_asynchronous: bool
Controls whether the archive is loaded/saved asynchronously. If set to False
, data loading is done sequentially.
Below is an overview of the most important methods in CWArchive.
__init__(path: str, asynchronous: bool = True, delay: float = 0.07)
Initializes a new archive with the specified file path, async flag, and an optional delay for asynchronous loads.
Parameters:
path (str)
: The path to the archive file on disk.asynchronous (bool)
: Determines if loading is handled asynchronously (True
by default).delay (float)
: Time in seconds to wait between asynchronous load operations. Defaults to 0.07
.Raises:
TypeError
: If asynchronous
is not a boolean.Potential Race Condition:
If the asynchronous loading processes attempt to modify shared data at the same time, errors can occur. Consider increasing delay
or setting archive_asynchronous
to False
.
__str__() -> str
Returns a user-friendly string with the path of the archive, e.g., "<Archive | path=/path/to/archive>"
.
__repr__() -> str
Returns a formal string representation of the archive for debugging purposes, e.g., "Archive(path='...')"
.
__len__() -> int
Returns the count of items (key-value pairs) currently in the archive.
__add__(other: Chat | Bot | Model)
Enables using the +
operator to add a Chat
, Bot
, or Model
object to the archive.
my_archive = CWArchive("chats.archive")
my_archive + my_chat # Adds 'my_chat' under the next available ID
__sub__(other: int | Chat | Bot | Model)
Enables using the -
operator to remove an element from the archive by its integer ID or by an instance of Chat
, Bot
, or Model
.
my_archive - 0 # Removes the item with ID 0
my_archive - my_chat # Removes the specific Chat instance
__enter__(self, *args, **kwargs) -> CWArchive
Returns the CWArchive
instance upon entering a with block, allowing you to perform archive operations within that scope.
with CWArchive(path="my_archive.txt") as archive:
...
__exit__(self, *args, **kwargs) -> None
Called automatically upon exiting the with block. By default, it invokes save(), ensuring that any modifications made to the archive during the block are persisted to disk.
with CWArchive(path="my_archive.txt") as archive:
# All changes, like adding or removing objects,
# will be saved when exiting this block.
define(path: str, delay: float) -> None
Updates the archive file path and the delay for asynchronous operations.
get_id_from_element(element: Chat | Bot | Model) -> list[int]
Returns a list of all IDs in the archive that correspond to the provided object. Useful if the same object was stored multiple times.
is_valid_id(identifier: int) -> bool
Checks whether the given ID exists in the archive.
add(element: Chat | Bot | Model) -> None
Inserts an element (if it is an instance of Chat
, Bot
, or Model
) into the archive under the next available integer ID.
remove(element: list | set | tuple | int | Chat | Bot | Model, remove_type: str | None = "all") -> None
Removes one or multiple elements from the archive.
element
: Can be a single ID, a single object, or an iterable of IDs/objects.remove_type
: Accepts "all"
, "first"
, or "last"
to handle cases where the same object appears more than once.save() -> None
Serializes and writes the archive data to disk in sorted order (by the object’s representation).
my_archive.save() # Commits changes to file
retrieve() -> dict[int, Chat | Bot | Model]
Reads the archive file from disk and converts each item’s string representation into its corresponding object. Supports both synchronous and asynchronous loading.
archive_delay
seconds.archive_asynchronous
is False
, loads data one item at a time.from chatweaver import CWArchive, Chat
# 1. Create an archive (asynchronous by default) with a specific file path
archive = CWArchive(path="my_archive.txt")
# 2. Add a new Chat object to the archive
my_chat = Chat(api_key="sk-1234567890abcdef...", title="Session One")
archive.add(my_chat)
# 3. Save the archive to disk
archive.save()
# 4. Retrieve data from the archive (asynchronously, in chunks by default)
loaded_data = archive.archive_data # Remember, it's better to use the archive_data attribute instead of retrieve()
for item_id, item_obj in loaded_data.items():
print(item_id, item_obj)
# 5. Remove the chat by its ID (e.g., 0)
archive.remove(0)
archive.save() # Reflect changes on disk
# 6. Disable asynchronous loading if you run into concurrency issues
archive.archive_asynchronous = False
In this example, we initialize a CWArchive
, add a Chat
to it, and then save and retrieve data. If concurrency errors appear due to asynchronous operations, you can either increase archive_delay
or set archive_asynchronous
to False
to force sequential processing.
from chatweaver import CWArchive, Bot
my_bot = Bot(api_key="sk-1234567890abcdef...", rules="Be helpful!", name="HelperBot")
with CWArchive(path="my_archive.txt") as archive:
archive.add(my_bot)
# No need to manually call archive.save()
When using CWArchive as a context manager:
__enter__
is called at the start of the with block, returning the instance.__exit__
is automatically called at the end, ensuring save() is executed.FAQs
A Python library that simplifies building AI-driven chatbots with OpenAI, offering conversation management, file attachments, and persistent storage in one cohesive package.
We found that chatweaver demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
We’ve redesigned the Socket dashboard with simpler navigation, less visual clutter, and a cleaner UI that highlights what really matters.
Industry Insights
Terry O’Daniel, Head of Security at Amplitude, shares insights on building high-impact security teams, aligning with engineering, and why AI gives defenders a fighting chance.
Security News
MCP spec updated with structured tool output, stronger OAuth 2.1 security, resource indicators, and protocol cleanups for safer, more reliable AI workflows.