[拆解LangChain执行引擎-18]Agent状态是如何从通道读取的?

MuleSoft+LangChain双引擎架构:企业AI编排实战指南 AI编排(AI Orchestration)是连接大模型与企业核心系统的关键技术范式,其本质在于解决确定性系统与概率性模型之间的范式冲突。通过协议转换、语义推理与结构化数据治理,实现安全、可审计、可回滚的AI能力落地。MuleSoft承担企业能力抽象与可信数据路由,LangChain负责动态Prompt组装、多步推理链与工具调用等AI原生逻辑,二者协同构成‘物理层+逻辑层’双引擎架构。该模式已广泛应用于销售智能助手、贷后预警、售后知识库等高合规要求场景,成为ERP/CRM与LLM之间不可或缺的‘翻译官’和‘ 阅读详情

在Agent状态是如何被写入通道的?中,我们探讨了组成的Agent的节点在完成了自身操作后,如何将执行结果通过写入相应的通道,进而更新Agent的状态。本篇文章则讨论这个问题的另一面:节点如何通过读取通道得到Agent的状态的。

1. 利用ChannelRead读取状态

通过Agent状态是如何被写入通道的?,我们知道作为Agent节点的PregelNode对象利用ChannelWrite提交它对通道的写入意图,进而增量更新Agent的状态。ChannelRead与之相对,它被PregelNode用于读取相应的通道进而得到所需的状态成员,这个操作可以通过如下所示的静态方法do_read来完成。

class ChannelRead(RunnableCallable):
    @staticmethod
    def do_read(
        config: RunnableConfig,
        *,
        select: str | list[str],
        fresh: bool = False,
        mapper: Callable[[Any], Any] | None = None,
    ) -> Any

静态方法do_read具有如下的参数:

  • config:当前的运行时配置;
  • select:选择需要读取的通道,如果没有指定,将不会读取任何通道;
  • fresh:如果设为True,它会强制获取当前状态下最新鲜的数据,而不是可能被缓存的旧值。默认值为False,以提高性能;
  • mapper:对读取的内容(字典形式)作进一步转换,以生成最终返回的对象;

下面的程序演示了针对do_read方法的使用。我们创建了一个单节点的Pregel对象,并为它定义了5个通道,其中foo、bar、baz和select为输入通道,前三个通道用于提供常规的输入,select通道用于提供需要被节点读取的通道列表。节点订阅select通道,并将该通道的值作为参数调用do_read方法,作为运行时配置的config参数直接注入到节点函数。do_read方法返回的结果被写入result通道,该通道也是Pregel的唯一输出通道。

from langgraph.pregel import Pregel, NodeBuilder
from langgraph.pregel._read import ChannelRead
from langgraph.channels import LastValue
from typing import  Any
from langchain_core.runnables import RunnableConfig

def read(channels:list[str], config: RunnableConfig) -> Any:
    return ChannelRead.do_read(config, select=channels)

node = (NodeBuilder()
        .subscribe_only("select")
        .write_to("result")
        .do(read))

app = Pregel(
    nodes={"node": node},
    channels={
        "foo":LastValue(str),
        "bar":LastValue(str),
        "baz":LastValue(str),
        "select":LastValue(list),
        "result":LastValue(Any)
    },
    input_channels=["foo", "bar", "baz","select"],
    output_channels=["result"],
)

input = {"foo": "123", "bar": "456", "baz": "789"}

result = app.invoke(input={**input, "select": ["foo"]})
assert result["result"] == {"foo": "123"}

result = app.invoke(input={**input, "select": ["foo", "bar"]})
assert result["result"] == {"foo": "123", "bar": "456"}

result = app.invoke(input={**input, "select": ["foo","bar", "baz"]})    
assert result["result"] == {"foo": "123", "bar": "456", "baz": "789"}

result = app.invoke(input={**input, "select": []})
assert result["result"] == {}

Pregel对象创建之后,我们利用作为输入的字典为foo、bar和baz指定相同的值,但设置不同的select列表。我们将输入字典作为参数对Pregel发起多次调用,断言验证了返回值是否与select列表的一致性。

2. ChannelRead

静态方法do_read在ChannelRead中的定义非常简单,针对选择通道的读取并未真正实现在该方法中,一切都隐藏在它通过RunnableConfig中提取出来的这个可执行对象。

class ChannelRead(RunnableCallable):
    @staticmethod
    def do_read(
        config: RunnableConfig,
        *,
        select: str | list[str],
        fresh: bool = False,
        mapper: Callable[[Any], Any] | None = None,
    ) -> Any:
        try:
            read: READ_TYPE = config[CONF][CONFIG_KEY_READ]
        except KeyError:
            raise RuntimeError(
                "Not configured with a read function"
                "Make sure to call in the context of a Pregel process"
            )
        if mapper:
            return mapper(read(select, fresh))
        else:
            return read(select, fresh)

RunnableConfig在LangChain执行引擎中被当成数据总线在用,如果你对其底层实现稍有了解,你会发现它将很多东西往里面扔。我不想评论这种设计的优劣,但我个人是不太喜欢的。在Agent状态是如何被写入通道的?中,我们知道它在配置中为ChannelWrite的do_write方法存放了一个用于收集(channel_name, channel_value)二元组的函数,对应的Key为__pregel_send,通过常量CONFIG_KEY_SEND表示。这里也一样,它在配置存放了一个同于读取通道的函数,对应的Key为__pregel_read,通过常量CONFIG_KEY_READ表示。通过给出的实现,可以推断这个函数的签名为Callable[[list[str],bool],dict[str,Any]|Any]。

3. local_read

在Agent状态是如何被写入通道的?提到过,用于收集通道写入的函数是在创建节点对应执行任务的PregelExecutableTask对象时创建的,携带此函数的RunnableConfig也被绑定在这个PregelExecutableTask对象上。这个用于通道读取的函数的创建和应用方式与之类似。这个被置于RunnableConfig中的Callable[[list[str],bool],dict[str,Any]|Any]是针对如下这个local_read函数创建的偏函数。

def local_read(
    scratchpad: PregelScratchpad,
    channels: Mapping[str, BaseChannel],
    managed: ManagedValueMapping,
    task: WritesProtocol,
    select: list[str] | str,
    fresh: bool = False,
) -> dict[str, Any] | Any

ManagedValueMapping = dict[str, ManagedValueSpec]

local_read函数具有如下的参数:

  • scratchpad:在推进Pregel执行的每一步(Superstep)对会创建的PregelScratchpad,用于存放当前超步数以及服务于中断恢复执行和SubAgent执行的计数器。所有ManagedValue的值都是根据它计算出来的;
  • channels:所有通道与名称的映射;
  • managed:所有ManagedValue的描述对象(ManagedValueSpec)与名称的映射;
  • task:节点任务的协议,主要偏重于描述节点产生的状态更新;
  • select:选择读取的通道列表;
  • fresh:如果设为 True,它会强制获取当前状态下最新鲜的数据,而不是可能被缓存的旧值。默认值为False,以提高性能;

WritesProtocol协议定义如下,上面提到过的用于表示节点执行任务的PregelExecutableTask就实现了这个协议。它提供的四个属性分别表示任务的路径(SubAgent导致)、名称、通道写入(channel_name+channel_value二元组序列)和订阅通道。

class WritesProtocol(Protocol):
    @property
    def path(self) -> tuple[str | int | tuple, ...]: ...
    @property
    def name(self) -> str: ...
    @property
    def writes(self) -> Sequence[tuple[str, Any]]: ...
    @property
    def triggers(self) -> Sequence[str]: ...

如下所示的是local_read函数的完整实现:它利用select参数从channels和managed筛选出通道和ManagedValueSpec,然后调用read_channels将选择的通道和ManagedValue的值读出来。如果fresh参数被设置成True,它会对选择出来的通道先实施写操作来清除缓存。

def local_read(
    scratchpad: PregelScratchpad,
    channels: Mapping[str, BaseChannel],
    managed: ManagedValueMapping,
    task: WritesProtocol,
    select: list[str] | str,
    fresh: bool = False,
) -> dict[str, Any] | Any:
    updated: dict[str, list[Any]] = defaultdict(list)
    if isinstance(select, str):
        managed_keys = []
        for c, v in task.writes:
            if c == select:
                updated[c].append(v)
    else:
        managed_keys = [k for k in select if k in managed]
        select = [k for k in select if k not in managed]
        for c, v in task.writes:
            if c in select:
                updated[c].append(v)
    if fresh:
        # apply writes
        local_channels: dict[str, BaseChannel] = {}
        for k in channels:
            cc = channels[k].copy()
            cc.update(updated[k])
            local_channels[k] = cc
        # read fresh values
        values = read_channels(local_channels, select)
    else:
        values = read_channels(channels, select)
    if managed_keys:
        values.update({k: managed[k].get(scratchpad) for k in managed_keys})
    return values

在为节点创建任务的时候,它会提取节点的名称、订阅通道和当前的PregelScratchpad、所有通道和描述所有ManagedValue的ManagedValueSpec与其名称的映射字典,按照如下的方式调用创建local_read的偏函数。这个偏函数被置于绑定到节点任务的RunnableConfig配置中,供ChannelRead的静态方法do_read使用。代码中的那个writes变量就是那个用于收集通道写入意图的双端队列(deque)。

name = ...
writes = ...
triggers = ...
scratchpad = ...
channels = ...
managed = ...

partial(
    local_read,
    scratchpad,
    channels,
    managed,
    PregelTaskWrites(
        task_path[:3],
        name,
        writes,
        triggers,
    ),
),

class PregelTaskWrites(NamedTuple):
    path: tuple[str | int | tuple, ...]
    name: str
    writes: Sequence[tuple[str, Any]]
    triggers: Sequence[str]

顺便说说为什么叫local?在LangGraph的并行执行模型中,当一个节点执行完毕并返回结果时,这些结果属于局部更新,尚未合并到全局状态中。

4. read_channels

local_read函数用于读取通道的read_channels函数定义如下。没什么特别之处,最终就是调用BaseChannel的get方法,并在此基础上做了一些必要的异常处理而已。

def read_channels(
    channels: Mapping[str, BaseChannel],
    select: Sequence[str] | str,
    *,
    skip_empty: bool = True,
) -> dict[str, Any] | Any:
    if isinstance(select, str):
        return read_channel(channels, select)
    else:
        values: dict[str, Any] = {}
        for k in select:
            try:
                values[k] = read_channel(channels, k, catch=not skip_empty)
            except EmptyChannelError:
                pass
        return values

        def read_channel(
    channels: Mapping[str, BaseChannel],
    chan: str,
    *,
    catch: bool = True,
) -> Any:
    try:
        return channels[chan].get()
    except EmptyChannelError:
        if catch:
            return None
        else:
            raise

5. 作为Runnable的ChannelRead

对于ChannelRead,我们仅仅介绍了它的静态方法do_read,而它自身是一个继承自RunnableCallable的可执行对象,从如下的定义可以看出,最终用来读取通道的_read和_aread方法最终还是调用的静态方法do_read。

class ChannelRead(RunnableCallable):
    channel: str | list[str]
    fresh: bool = False
    mapper: Callable[[Any], Any] | None = None

    def __init__(
        self,
        channel: str | list[str],
        *,
        fresh: bool = False,
        mapper: Callable[[Any], Any] | None = None,
        tags: list[str] | None = None,
    ) -> None:
        super().__init__(
            func=self._read,
            afunc=self._aread,
            tags=tags,
            name=None,
            trace=False,
        )
        self.fresh = fresh
        self.mapper = mapper
        self.channel = channel

    def get_name(self, suffix: str | None = None, *, name: str | None = None) -> str:
        if name:
            pass
        elif isinstance(self.channel, str):
            name = f"ChannelRead<{self.channel}>"
        else:
            name = f"ChannelRead<{','.join(self.channel)}>"
        return super().get_name(suffix, name=name)

    def _read(self, _: Any, config: RunnableConfig) -> Any:
        return self.do_read(
            config, select=self.channel, fresh=self.fresh, mapper=self.mapper
        )

    async def _aread(self, _: Any, config: RunnableConfig) -> Any:
        return self.do_read(
            config, select=self.channel, fresh=self.fresh, mapper=self.mapper
        )
垂域AI落地实战:LangChain与LangGraph的生产级架构设计 垂域AI指在医疗、金融、工业等垂直领域中,将大语言模型与强约束业务逻辑深度结合的技术实践。其核心在于解决可追溯性、确定性边界和失败可降级三大刚性需求,而非泛化通用能力。LangChain通过Chain、RouterChain、Tool等组件提供结构化编排能力,而LangGraph以状态机+有向无环图(DAG)建模,显著提升复杂流程的可控性与可观测性。技术价值体现在将非结构化输入(如病历、工单、录音)转化为可审计、可回滚、可监控的决策链路。典型应用场景包括合规审查、设备故障诊断、智能问诊等高容错要求系统。本文 阅读详情

相关推荐

Agent工作流本质:状态机契约与可验证执行

Agent工作流并非可视化节点连线,而是基于确定性输入输出契约的状态机系统。其核心原理在于将模糊自然语言指令,通过Schema校验、错误分类、重试策略等机制,转化为可中断、可回溯、可验证的执行过程。技术价值体现在提升容错能力、保障数据一致性、支持审计与降级,广泛应用于HR审批、金融对账、CRM集成等企业级场景。本文聚焦WorkBuddy底层机制拆解,揭示Skill与Agent的本质差异,并以Python手写最小内核的方式,还原从协议层到语义层的完整工作流构建逻辑。

weixin_34396902的博客 327

[拆解LangChain执行引擎-08]基于Checkpoint的持久化

Pregel基于Checkpoint的持久化机制是实现Agent应用`高可用性`和`长期记忆`的基础,它本质上是将 不断向前推进的图在“Superstep”之间将其状态固化的过程。和很多数据库持久化类似,Pregel采用`基于全量数据的状态快照+基于增量更新的操作日志`的持久化策略。

JaydenAI的博客 807

LangChain Tools、MCP Tools与Function Calling 三者分工解析

大模型智能体(Agent)中的工具调用能力,本质是‘意图理解→结构化决策→标准化执行’的技术闭环。Function Calling 是模型内置的结构化意图解析引擎,决定能否识别并生成工具调用指令;LangChain Tools 是面向开发者的工具封装范式,解决多源异构系统在统一框架下的可调度性问题;MCP Tools 则定义了模型与工具间通用的通信契约,确保参数传递、错误处理与流式响应的跨平台一致性。三者分属能力层、工程层与协议层,不可替代亦不可混淆。本文结合7个生产级落地案例,深入剖析其协同机制与典型误用

weixin_34075268的博客 361

从 llms.txt 目录生态看 XERJ 的 Agent 接入模式:18 条目录调研发现的深度拆解与落地清单

> 本文基于 XERJ 仓库中 [docs/research/llms-txt-2026-09/discovery-directories.md](https://link.gitcode.com/i/3e28bccf1f3cb2337dcf716147654a98) 这份 2026-09-18 的目录调研笔记展开。它系统梳理了 llmstxt.org、directory.llmstxt.clou

gitblog_00906的博客 1101

LangGraph实战:用状态机图编排构建可落地的AI Agent工作流

AI Agent本质是面向任务的自动化决策系统,其核心挑战在于状态管理、错误恢复与动态流程控制。LangGraph通过有向无环图(DAG)建模,将Agent重构为显式状态机,以TypedDict定义数据契约、conditional_edge实现业务逻辑驱动的条件跳转、内置循环与检查点保障韧性执行。相比传统Chain的线性无状态模式,LangGraph让AI行为具备可追溯、可中断、可审计的工程确定性,特别适用于合同审核、工单处理、数据同步等需多步校验与人工协同的真实场景。本文聚焦LangGraph的核心机制与

weixin_30240349的博客 325

OpenMinis移动端AI Agent实践:从架构拆解到落地避坑指南

AI Agent正从云端走向移动端,区别于传统聊天机器人的一问一答,Agent需要具备感知、规划、行动、观察的完整闭环,在手机有限的算力与内存中实现多步任务自主执行。移动端大模型部署面临量化、推理延迟、功耗与隐私的多重约束,端云协同与工具调用成为关键工程问题。通过统一工具协议、任务调度引擎与上下文管理,开发者可以在手机上构建真正可用的个人助理类应用。本文基于OpenMinis开源项目,拆解其混合架构设计思路,覆盖模型量化选型、NPU加速、后台任务生命周期、权限安全分级等实践要点,并总结工具调用幻觉、发热耗电

weixin_34355559的博客 534

智能数据Agent实战:从GMV拆解到自动化决策的电商增长引擎

在电商增长进入存量竞争阶段,传统经验决策与人工执行已难以应对海量实时数据带来的复杂判断。智能数据Agent作为一种能够自主感知环境、制定计划并执行动作的决策系统,正成为连接数据洞察与业务动作的关键技术。它通过实时数据管道与分层强化学习,将GMV目标拆解为流量、转化率、客单价与复购系数等可优化指标,并自动输出定价调整、优惠券发放、库存预判等具体动作。在动态定价、智能选品、用户流失召回等典型场景中,Agent不仅能提升决策效率,还能在毛利约束下持续优化增长质量。本文从系统架构、核心算法到落地踩坑,梳理了基于实时

weixin_34221775的博客 344

LangGraph.js多Agent系统开发:从工作流原理到企业级实践

工作流引擎是现代AI应用开发中的核心技术概念,它通过状态机模型将复杂任务分解为可管理的执行单元。其技术原理基于有向图结构,每个节点代表特定的处理逻辑,边定义执行路径,从而实现任务的有序流转。在AI工程实践中,工作流的价值在于解决单个模型处理复杂任务时的稳定性问题,通过多Agent专业化分工提升系统可靠性。LangGraph.js作为专门的多Agent系统框架,将工作流概念与AI开发深度结合,支持条件路由、循环执行等高级特性。在智能客服、内容审核、业务流程自动化等应用场景中,开发者可以基于状态机理念构建可预测

weixin_30813225的博客 297

Harness Engineering 深度解读:Agent = 模型 + Harness,11 个主流编程 Agent 源码拆解丨论文解读

一句话结论:Agent = 模型 + Harness。模型提供智能,Harness 把智能变成工作。 本文深度拆解了 11 个主流生产级编程 Agent(如 Claude Code、Codex、Gemini CLI 等)的约 400 万行源代码,系统梳理了“Harness Engineering(驾驭工程)”的核心架构与演化趋势。 🎯 核心认知:什么是 Harness? Harness 是模型之外的一切运行时系统。它包含七个核心子系统:智能体循环(Agent Loop)、LLM 集成、工具与动作、记忆

m0_56491492的博客 433

MuleSoft+LangChain双引擎:企业AI编排的工程化落地实践

AI编排(AI Orchestration)是企业级大模型应用落地的核心能力,它解决的不是模型生成质量,而是多系统数据协同、安全可控路由与合规数据编织等确定性工程问题。其底层原理在于将LLM的语义理解能力与企业集成平台的语法治理能力解耦分工——前者专注推理链与RAG增强,后者承担OAuth鉴权、字段级脱敏、决策表路由及DataWeave数据标准化。这种架构显著提升AI系统的可审计性、可维护性与GDPR/等保合规性,广泛应用于销售智能助手、贷后风险预警、CRM智能摘要等强流程、高权限、多源异构场景。本文即基于

ailiao2015的博客 377

AI Agent四层构建法:意图、决策、执行、反馈的工程化落地

AI Agent并非简单调用大模型的智能体,而是一个需分层解耦、可测量可运维的工程系统。其核心在于将模糊的‘自主行为’转化为结构化技术栈:意图层解决自然语言到业务语义的精准映射,决策层将LLM降级为规则编译器以保障确定性,执行层强调工具即契约的强约束接入,反馈层则通过显性/隐性/系统三重信号驱动秒级迭代。该范式直击生产环境中循环调用、上下文爆炸、工具失灵等高频故障根源,适用于电商、制造、保险等强业务逻辑场景,是RAG与Agent本质区别的实践锚点。

virusswb的专栏 439

从Windows到Agent网络:AI超级应用的技术演进与实践指南

在人工智能技术飞速发展的今天,AI Agent(智能体)作为能够感知环境、自主规划并执行任务的软件实体,正成为连接大语言模型与真实世界的关键桥梁。其核心原理在于通过工具调用(Tool Calling)机制,将LLM的推理能力与外部函数、API等具体操作相结合,从而实现对数字和物理世界的交互。这一技术架构为自动化复杂工作流、构建智能助手提供了工程基础,具有广泛的应用前景。从代码生成、数据分析到客服自动化,AI Agent正在重塑软件开发和业务流程。本文聚焦于AI Agent的核心能力框架,特别是Agent S

weixin_34221775的博客 405

Agent技术面试指南:核心架构与实战解析

智能体(Agent)技术作为分布式人工智能的核心实现形式,通过感知-决策-执行闭环实现自主行为。其技术原理结合了强化学习、多任务调度等算法,在自动化业务流程和人机协作场景中展现巨大价值。当前主流技术栈包含LangChain框架、gRPC通信协议和向量数据库等组件,广泛应用于电商推荐、物流调度等场景。特别是在大模型时代,基于RAG增强和联邦学习的Agent系统成为技术热点。面试考察重点包括多Agent冲突解决、经验回放机制等工程实践细节,这些能力直接影响系统吞吐量和响应延迟等关键指标。

weixin_30607029的博客 490

LangChain工程化落地:生产级LLM应用的分层架构与稳定性实践

LangChain作为大语言模型(LLM)应用开发的关键编排框架,其核心价值不在于封装能力,而在于连接异构AI组件并保障可观测性。本文从RAG、Agent、Chain等基础技术原理出发,解析如何通过四层解耦架构(接入层、编排层、能力层、数据层)实现低耦合、高可控的工程落地;强调Prompt Engineering与PydanticOutputParser在结构化输出和版本管理中的技术价值;结合混合检索(BM25+向量)、超时重试降级、Plan-and-Execute Agent等实战策略,支撑合同审查、竞品

weixin_33947521的博客 481

DeepSeek V4:面向工程落地的AI Agent工作流引擎

AI Agent正从概念验证走向真实工程闭环,其核心在于将大模型能力深度耦合到开发、运维与数据工作流中。原理上,它依赖多源上下文联合推理(如HTTP协议状态机、云平台API规范、SQL执行引擎特性),而非单点文本生成;技术价值体现在自主决策、工具调用约束校验与跨抽象层因果推演,显著降低长链任务的容错成本;典型场景覆盖API异常自愈、跨云故障响应、遗留系统文档重建、自然语言SQL编译及技术方案可行性沙盒验证。DeepSeek V4正是这一范式的代表性实践,尤其在HTTP协议分析、云原生自治脚本生成和Java字

weixin_30411819的博客 447

Agent Runtime 层的范式迁移:从上下文状态到事件日志

Agent runtime 是 AI 工程栈中承上启下的关键抽象层,其核心职责是管理会话状态、调度工具执行与保障沙箱安全。传统方案将 session 状态强耦合于 LLM 的 context window,导致语义衰减、不可审计与扩展瓶颈;而新一代架构如 Anthropic Managed Agents 和 AWS Bedrock AgentCore 推动‘Session-as-Event-Log’成为事实标准——通过原子化、带时间戳、不可变的事件流替代滚动上下文,实现可重放、可审计、可水平扩展的会话治理。

weixin_34347651的博客 366

JIT-Agent:动态生成智能体框架,让大模型自主规划工具与执行路径

AI Agent 正从固定流程走向动态决策。传统智能体常把工具调用顺序写死在代码中,导致需求变化时频繁改版,模型推理能力也被严重浪费。JIT-Agent 借鉴即时编译思想,在请求到达时动态生成智能体的执行计划:由大模型充当规划器,通过工具装配与调度执行,实时决定调用哪个模型、使用哪些工具以及步骤顺序。这种基于运行时生成的智能体框架,解决了工具组合爆炸、业务需求多变和模型能力利用不足等核心问题,适用于运维助手、数据分析、办公自动化等任务开放、工具密集的场景。本文不仅讲解 JIT-Agent 的核心概念与架构分

313

Agent Runtime三层架构:Session、Harness与Sandbox解耦实践

Agent Runtime 是大模型应用落地的核心基础设施层,其本质是为智能体提供可信赖的执行环境——涵盖状态持久化、无状态调度与安全沙箱隔离。它源于对传统LLM应用中上下文脆弱、状态丢失、凭证泄露等工程痛点的系统性重构,技术价值在于将非功能需求(可观测性、可审计性、合规性、灾备能力)标准化、服务化。典型应用场景包括企业级知识助手、销售线索分发、PR自动生成等需高可靠工作流的AI系统。本文深入剖析Anthropic Managed Agents所倡导的Session事件日志化、Harness无状态化、San

weixin_34379433的博客 389
上一篇: [拆解LangChain执行引擎-17]Agent状态是如何被写入通道的?
下一篇: [LangChain智能体本质论-06]赋予Agent执行力的工具是个什么东西?
JaydenAI
博客等级 码龄1年 241粉丝 319原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值